Errors and Status Codes

How bem reports failures, how to retry safely, and how to handle partial successes

Hand off to an LLM

bem distinguishes two kinds of failure: request errors, returned synchronously when the API can't accept your call, and execution errors, which appear inside otherwise-successful workflow calls when one or more nodes fail. Both shapes are stable — your error-handling code only needs to know two things.

HTTP status codes

CodeMeaningWhen you'll see it
200 OKSuccess, body returnedMost reads; wait=true calls that completed
202 AcceptedAccepted for async processingWorkflow calls without wait=true; eval queueing; collection item ingest
204 No ContentSuccess, no bodyDeletes
207 Multi-StatusPartial successBatch updates where some items succeeded and some failed (e.g. update-transformation)
400 Bad RequestInvalid requestSchema violation, unsupported inputType, malformed outputSchema, contradictory filters
401 UnauthorizedMissing or invalid API keyThe x-api-key header is missing, malformed, or revoked
404 Not FoundResource doesn't existWrong functionName/workflowName/callID, or you're targeting a different environment
422 Unprocessable EntityRequest shape valid, semantics notBody parses but violates a model constraint (e.g. workflow mainNodeName not in nodes)
429 Too Many RequestsRate limit exceededBack off and retry
500 Internal Server ErrorServer-side failureTreat as retryable with backoff; if persistent, contact support with the response body

Request-error shape

Every non-2xx response uses the same body schema:

{
  "message": "human-readable description",
  "code": 400,
  "details": { "field": "outputSchema", "reason": "..." }
}
FieldTypeNotes
messagestringAlways present. Safe to surface to operators; not necessarily safe to surface to end users (may include resource names).
codeintegerOptional. Mirrors the HTTP status when present.
detailsobjectOptional, free-form. Carries field-level context for 400/422 responses; absent for most 500s.

Treat the body as advisory and the HTTP status as authoritative. Don't switch on details.field strings — they're meant for humans, not parsers.

Execution errors inside workflow calls

When a workflow call partially or fully fails, the HTTP response is still 200 (or 202 if you didn't pass wait=true). The failure information lives inside the call object:

{
  "call": {
    "callID": "wc_abc123",
    "status": "failed",
    "outputs": [
      { "eventID": "ev_001", "eventType": "transform", "transformation": { ... } }
    ],
    "errors": [
      {
        "eventID": "ev_002",
        "functionCallID": "fc_abc",
        "workflowNodeName": "invoice-extractor",
        "errorMessage": "outputSchema constraint violation: field 'totalAmount' is required",
        "createdAt": "2024-04-25T19:14:02Z"
      }
    ],
    "url": "/v3/calls/wc_abc123",
    "traceUrl": "/v3/calls/wc_abc123/trace"
  }
}

Two things to note:

  1. outputs and errors are not mutually exclusive. A workflow with three nodes can emit two terminal outputs and one error. Always check both.
  2. call.status reflects the worst outcome. It's completed only if every terminal node produced a non-error event. Any error event flips it to failed. For per-node detail, fetch the trace at traceUrl.

Retry guidance

StatusRetry?How
429YesHonour Retry-After if present, otherwise exponential backoff starting around 1s, capping near 10s.
500/502/503/504YesExponential backoff with jitter, max 5 attempts.
408YesSame as 5xx.
400/401/404/422NoThe request itself needs to change; retrying as-is won't help.
409SometimesWhen returned on a workflow create with a name collision, treat as terminal.

Idempotency

bem uses callReferenceID (on workflow calls) as your deduplication key. Submitting the same callReferenceID for the same workflow within a short window returns the existing call instead of creating a new one — safe to retry network failures without producing duplicates.

For all other operations (function/workflow create + update), use the response's stable IDs (functionID, workflowID) to detect whether your retry succeeded after a network blip.

Common errors and what they mean

Message fragmentWhat it meansFix
outputSchema constraint violationExtracted JSON doesn't satisfy your outputSchema (usually a missing required field)Surface as a workflow output error, not a 4xx — see call.errors[].errorMessage. Tighten upstream prompts or relax the requirement.
unsupported inputTypeThe inputType you sent isn't in the supported listSee Supported file types.
function name already existsYou called create with a name that's already in use in this environmentEither update the existing function or pick a new name.
workflow mainNodeName must be one of nodes[].nameTopology mismatchFix the request body.
BadRequestError: model state limit exceededThe outputSchema is too large/complex for the underlying modelSee Known limitations. Split the schema or reduce nesting.

Observing errors after the fact

The /v3/errors endpoint lists terminal error events across calls and is the right place to power monitoring dashboards or alerts. Filter by workflowNames, functionNames, or callIDs to scope to a specific surface.

On this page