Troubleshooting

The 20 most common issues encountered when using Priostack, with causes and step-by-step fixes.

Authentication and Authorization

ProblemCauseFix
401 Unauthorized on every request Missing or invalid X-API-Key header, or the key was rotated/deleted. Check your key in your dashboard: the signed-in owner can reveal the full key at any time. Send it as X-API-Key: <key> (the header name is case-insensitive), as Authorization: Bearer <key>, or as ?api_key=. Verify the environment variable is set: echo $PRIOSTACK_API_KEY.
403 Forbidden on admin endpoint Calling an operator endpoint with a customer API key. Admin endpoints (/api/admin/*) belong to the Priostack operator and check a separate X-Admin-Key; no customer API key is accepted there. Use the /api/v1/ engine routes and the /api/ account routes instead.
403 Forbidden - email not yet verified Signing in (POST /api/login) with an address that was never confirmed. The body starts with email address not yet verified. The API key itself is only sent once the address is verified, in the welcome email. Click the link in the verification email. If it never arrived, check spam, then POST /api/resend-verification with the address. The link expires after 72 hours.

Credits and Billing

ProblemCauseFix
402 Payment Required when starting instance The balance cannot cover the 1 credit that starting an instance costs, or the account is disabled. The body reads {"error": "insufficient credits: have 0, need 1", "balance": 0, "buy": "..."}. Every verified account gains 100 free credits per whole day, on a rolling 24-hour clock from signup (not at midnight). A grant is paid at the next balance check, which runs every 6 hours, so it can land up to about 6 hours after it falls due. You can also buy a credit pack at /wallet. Your balance is shown in your dashboard. Subscribe to the credits.low webhook to be warned at 30, 20 and 10 credits.
Credits deducted but process didn't start A start that fails is refunded (invalid JSON answers 400, a process that is not deployed answers 422). But when the start succeeds and the run fails straight away (for example a gateway condition reads a variable that was never set), the instance is created in the INCIDENT state and the credit stays spent. Find it with GET /api/v1/process-instances?filter.state=INCIDENT. There is currently no REST call that resumes an INCIDENT instance: fix the cause (for example set the missing variable in the start call) and start a new instance.

Job Workers

ProblemCauseFix
Job not activating (activate returns an empty list) The type in your activate request doesn't match the zeebe:taskDefinition type in the BPMN, or the instance was started with a different API key (activation only returns your own jobs). Check the BPMN XML for the exact task type string. Types are case-sensitive. GET /api/v1/process-definitions/{key}/xml returns the deployed XML, and GET /api/v1/jobs lists your jobs without activating them.
Same job processed twice An active job is never handed to a second worker: there is no lock expiry. A job comes back to the queue only when a worker fails it with retries above 0, or when the server restarts (outstanding jobs are restored to waiting with the same key). Make your handler idempotent, using the job key for deduplication. The deadline field (activation + 5 minutes, in Unix milliseconds) is informational, and retries has nothing to do with it: retries only counts attempts.
Job stuck in "active" state Worker activated the job but crashed before completing or failing it. Nothing reclaims it on its own: the deadline is informational and there is no lock expiry, so the instance stays ACTIVE. Release the job with POST /api/v1/jobs/{key}/fail and retries above 0 (it is re-queued at once); GET /api/v1/jobs lists your job keys. A server restart also restores it to waiting. Make workers release their jobs on shutdown, as the language guides do.

Process Execution

ProblemCauseFix
Process instance stuck (no incident) Instance is waiting at a Message Catch Event, Timer, or User Task with no worker or user to advance it. Read the instance with GET /api/v1/process-instances/{key} to see where it waits. Message and signal waits have no hosted correlation API: they are ordinary jobs of type message:<name> (receive task), event:message:<elementId> or event:signal:<elementId> (catch events), which a worker activates and completes, with no correlation-key matching. For timers: check the timer definition. For user tasks: complete via Tasklist.
BPMN parse error on deploy Invalid XML syntax, missing required attributes, or unsupported BPMN elements. Validate your BPMN in the Designer before deploying. The deploy answers 422 {"error": "deploy failed: ..."}; the message names the element or the XML line at fault.
Process not starting (201 Created but instance never appears) Race condition in monitoring, or the instance completed immediately (e.g., no tasks). Check GET /api/v1/process-instances?filter.state=COMPLETED - the instance may have completed instantly. Or read it directly with GET /api/v1/process-instances/{key}, using the processInstanceKey the start call returned.
Exclusive gateway: "no sequence flow with true condition" None of the outgoing sequence flow conditions evaluated to true, and no default flow was defined. Add a default flow (flow without a condition, marked with a slash in BPMN diagrams) to handle the catch-all case. Ensure all possible variable states are covered.

DMN and FEEL

ProblemCauseFix
DMN decision not found The decisionId in the Business Rule Task doesn't match the deployed DMN decision. Check the id attribute of the <decision> element in your DMN file. IDs are case-sensitive. Deploy the DMN through POST /api/v1/models before starting the instance (POST /api/v1/process-definitions takes BPMN only); otherwise the instance goes to INCIDENT.
FEEL evaluation error: variable not found A FEEL expression references a variable that isn't set on the process instance at that point. Check the process flow to ensure the variable is set before the FEEL expression is evaluated. In a gateway condition, a variable that was never set makes the instance an INCIDENT, even in x = null, so initialise it (to null if need be) before the gateway. To test an expression with sample values, put it in a DMN table and call POST /api/v1/decisions/{decisionId}/evaluate, or start an instance with those variables: there is no stand-alone FEEL evaluator.
DMN hit policy UNIQUE: multiple rules matched Two or more rules in the decision table match the input, but the hit policy requires exactly one match. Review your decision table rules - they should be mutually exclusive when using UNIQUE. Add more specific conditions or switch to FIRST hit policy.

Webhooks

ProblemCauseFix
Webhook not firing The webhook does not list the event (an empty events list receives nothing), the event is not one Priostack fires (there are no instance, job or incident events), the URL resolves to a private or loopback address, or the endpoint answers a non-2xx status. List your webhooks with GET /api/v1/webhooks and their attempts with GET /api/v1/webhooks/{id}/deliveries, and send one with POST /api/v1/webhooks/{id}/test. Ensure your endpoint answers 2xx within 10 seconds. After 3 failed attempts in total a delivery is parked in GET /api/v1/dead-letters.
Webhook signature verification failing Using a framework that parses the body before you can read it raw (Express with JSON middleware). Read the raw body bytes before any parsing. In Express, use express.raw() instead of express.json() for the webhook route. The X-Priostack-Signature header is sha256= followed by the hex HMAC-SHA256 of the raw body, so compare against the whole value, prefix included.

Performance and Limits

ProblemCauseFix
429 Too Many Requests More than 300 requests in a sliding 60 seconds from one IP address. The limit is per IP, not per API key, and job activation is not exempt. The 429 is plain text with no Retry-After: back off about 60 seconds, since rejected requests still count. Three strikes ban the IP for 2 hours (every request then answers 403). Job activation answers at once, with no long polling, so workers must pause 1 to 5 seconds after an empty poll. See Rate Limits.
Memory issues with large variable payloads Storing large binary data or large arrays in process variables. Store large data externally (S3, database) and pass only the reference (URL, ID) as a process variable. Keep individual variable values under 1 MB.
Slow process instance queries Querying thousands of instances without filtering. Filter instance queries with ?filter.state=ACTIVE, filter.bpmnProcessId and filter.startAfter (RFC 3339). The list has no pagination (plain state, limit and offset are ignored), so narrow it with filters.
Still stuck? Check the FAQ, search the Community Forum, or open a support ticket from the Console. Include your X-Request-ID header value from the failed request.

Getting Help

Every API response carries an X-Request-ID header. It is the one thing that lets a request be found again in the server logs, so quote it whenever something is wrong and the cause is not on this page.

Include the X-Request-ID from the failing response when you contact support, for example X-Request-ID: 3f8a2b1c9d4e5f6a. Without it a 5xx is one line in a log nobody can locate.