ConceptsErrors

Errors

The error envelope, every public error code, and how to handle each.

Every failure answers with the same JSON envelope — error.code, a human-readable error.message, and error.meta with details that depend on the code — and an HTTP status that follows from its code.

For example, POST /v1/publish-requests sent without its Idempotency-Key header answers 400:

{  "error": {    "code": "validation_error",    "message": "The idempotency-key header is required for this operation.",    "meta": {      "validationErrors": [        {          "field": "header.idempotency-key",          "message": "Required header."        }      ]    }  }}

Branch on error.code, never on message. The codes are stable; the table below is generated from the same table the API answers with.

CodeStatusRetryMeaning
validation_error400NoThe request does not match the operation's input schema or fails an admission check. meta.validationErrors names every problem.
unauthorized401NoNo API key, or a key Koil does not accept (unknown, revoked, or with a prefix that does not match its mode).
invalid_token401NoThe provider credential behind the Connected Profile no longer works; the end user must re-authorize.
quota_exceeded402NoA free-plan hard cap is reached; GET /v1/billing/account reports the caps.
scope_insufficient403NoThe provider grant lacks a scope the operation needs; meta names the missing scopes.
not_found404NoThe resource does not exist in this Organization and mode.
conflict409NoThe request collides with current state: an idempotency key reused with a different payload or still in flight, a run already in progress, or a publish that has already started.
rate_limit_exceeded429After Retry-AfterKoil's own rate limit for the key, Organization, or client address is spent; retry after Retry-After seconds.
platform_rate_limit429After Retry-AfterThe provider throttled the call or the provider quota is spent; retry after Retry-After seconds.
internal500With backoffKoil or the provider failed: 500 for Koil, 502 for a provider answer Koil cannot use, or the provider's own 5xx. The message is generic; retry with backoff.
not_supported501NoThe provider or content type does not offer this operation.
service_unavailable503After Retry-AfterA service Koil needs to accept the request (API key validation) is unavailable. Nothing was attempted; retry after Retry-After seconds.

Validation errors

Every request is validated once, against the operation's input schema, and every problem is reported together. A validation_error carries:

  • meta.validationErrors — each with a field and message. Always present.
  • meta.violations — each with a code and a JSON-pointer path into the input. Present when the input schema or an admission check refused the request; a refusal before the input is assembled (a missing required header, a malformed cursor) has only validationErrors, as in the example above.

A body field the schema does not declare is refused with the violation code unknown_field rather than silently dropped, so a misspelled optional field never passes as an omitted one. Query-string values are converted to the schema's types before validation ("true" and "1" to a boolean, "10" to a number, a repeated key to an array); path parameters are strings.

Provider failures

When a provider refuses a call, Koil maps it onto the codes above: an expired or revoked grant is invalid_token, a missing permission scope_insufficient, a provider throttle or spent quota platform_rate_limit. Provider response detail may appear in meta when it is safe to show.

A failure on the provider's side is internal, never validation_error: a provider outage answers with the provider's own 5xx status, and a provider answer Koil cannot use (a response missing the id of what it just created, say) with 502. Retry both with backoff. internal errors never carry detail.

Retrying

The table's Retry column says what to do with each code: wait out the Retry-After header's seconds, retry with exponential backoff, or stop — those fail the same way until the request, the grant, or the resource changes. Writes that take an idempotency key are safe to retry with the same key.

On this page