Skip to content
DEVELOPERSThe essentials in 2 min

Errors, statuses and retries

The HTTP status of every failure, and what is safe to retry.

The outcome

Your integration reacts correctly to each kind of failure.

INPUT_ERRORCorrect the inputs
AUTH_ERRORRestore the connection
API_CHANGEDReview the repair
EXECUTION_ERRORInspect the outcome

Unknown write outcome? Check the site before retrying.

Workflow illustration · example data

Your path, in three steps.

  1. 01

    Read the status and body

    An invalid key returns a plain error field. A 429 refusal adds a message. These responses do not have an execution’s success field.

  2. 02

    Address the cause before retrying

    Correct the inputs, restore sign-in or wait for repair according to the code. An execution error does not guarantee that retrying is safe.

  3. 03

    Never repeat an action with an unknown outcome

    Check the record in the target software before sending anything again.

Want to go deeper?

Open just the topic you need.

Overview

Two things decide how your integration behaves when a connector fails: which of the four codes came back, and whether the request is safe to send again. This page covers both, and names the one case where retrying is the wrong thing to do even though everything looks retryable.

The status codes
HTTPWhenBody
200The connector ran and answered.The envelope, with success: true.
400An input is missing or the site rejected the value.The envelope, error.code is INPUT_ERROR.
400The connector is inactive or the request body is invalid.{ error, message }, with BRIDGE_NOT_ACTIVE or VALIDATION_ERROR.
401The key is missing or wrong, or the connector could not act as the signed-in user.A bare { "error": "…" } for a missing or wrong key; the envelope with AUTH_ERROR when the sign-in itself failed.
403The account has reached an applicable usage or plan limit.{ error, message } with the limit reason.
404The requested connector does not exist.{ "error": "NOT_FOUND", "message": "…" }.
429Rate limit, or five executions already running for the account.{ "error": "TOO_MANY_REQUESTS", "message": "…" } — not the envelope.
500Anything else: the site changed, a timeout, a transport failure.The envelope, error.code is API_CHANGED or EXECUTION_ERROR.

Some refusals do not use the execution envelope

A missing or invalid key returns { error }. Rate limits, inactive connectors, invalid request bodies and plan limits can return { error, message }, without success. Check the HTTP status and the shape of the body before reading an execution result.

The retry policy
CodeRetry?How
INPUT_ERRORNo.The same input fails identically. error.availableOptions often lists values that would work; error.sampleInput shows the shape expected.
AUTH_ERRORAfter access is restored.Read the connector’s status and complete reconnection if requested. A pause alone does not establish that access is restored.
API_CHANGEDAfter verification.Review the repair status. Repair may be running or need your attention; wait for a verified result before calling again.
EXECUTION_ERROROnly when safe.This code includes transient failures and runtime errors. For a read, a few attempts with increasing delays may help. For a write with an unknown outcome, stop and check the source site.
429Yes.Honour Retry-After when present. For the concurrency refusal there is no header: wait for your own in-flight calls to finish. Nothing is queued for you.
The rule that matters more than the codes

Never retry an action whose outcome you cannot see

When a connector that changes something sent its request and the answer never arrived, nobody can tell a booking that failed from a booking your customer now holds. Vela treats that state as final: it starts no repair and retries nothing. Your integration must do the same — read the record on the site, then decide.

Vela does not guarantee write idempotency. Sending the same request twice can create two records. Do not assume that an idempotency header is supported unless the connector contract explicitly provides that behavior.

The fields worth reading
Failure envelope
{
  "success": false,
  "data": null,
  "error": {
    "code": "INPUT_ERROR",
    "message": "no practitioner named \"Ana\" on this account",
    "availableOptions": ["Anna", "Anaïs"],
    "sampleInput": { "practitioner": "Anna", "date": "2026-09-21" }
  },
  "meta": { "executionId": "9e600e25-…", "scriptVersion": 3, "durationMs": 412, "sessionRenewed": false },
  "needsRepair": false
}
  • meta.executionId — quote this in a support request. It identifies the run, its input and the version that answered.
  • meta.scriptVersion — which version produced this result, so an old answer stays explainable.
  • meta.sessionRenewed — true when Vela signed in again during this very call. Useful when you are debugging latency: that call paid for a sign-in.
  • needsRepair — the error classification indicates a repairable failure. It does not prove that repair has started or succeeded; consult the connector status. An unknown write outcome blocks automatic repair.
Waiting for the answer

Every call answers with its result. ?async=true is accepted for older integrations and answered the same way. To watch the steps as they happen, use /stream.

What a failure does on Vela's side
  • An API_CHANGED on a healthy connector starts one automatic repair. An AUTH_ERROR makes Vela sign in again once, then ask you. A write with an unknown outcome never starts anything automatic.
  • A 429, a timeout or a network failure changes nothing about the connector's state. Ambiguous failures are never held against it.
  • An INPUT_ERROR is not a fault at all: the connector worked, the site said no.

The states this leads to are described in The life of a connector, and what happens next in How Vela repairs itself.

UP NEXTConnect an MCP client

One server address for the tools in your toolset.

Your situation doesn’t match the guide?

Talk to the team ↗