Error codes
Every ScaiScribe error is a structured envelope (spec §6.6):
1 2 3 4 5 6 7 8 | |
code values are stable across versions — match on them, not on message text. Messages are written for both humans and LLM agents: they name the offending field/value, list valid alternatives, and carry an explicit NOT a retriable error marker when repeating the request cannot succeed.
API-level codes#
| Code | HTTP | Retriable? | Meaning |
|---|---|---|---|
VALIDATION_FAILED |
422 | No | Request shape or value invalid. The message names the offending field(s) and the valid set. Fix the request; do not resend unchanged. |
NOT_FOUND |
404 | No | The referenced resource doesn't exist or isn't visible to your tenant (cross-tenant resources report 404, not 403 — existence isn't leaked). |
UNAUTHENTICATED |
401 | After re-auth | Missing/expired/invalid token, or a service token missing the X-ScaiScribe-Tenant-Id header. |
FORBIDDEN |
403 | No | Authenticated but not allowed (missing role, builtin-theme deletion, etc.). |
QUOTA_EXCEEDED |
403 | After quota reset | A tenant quota axis is exhausted. details carries {axis, limit, used, increment}. renders_per_day resets daily; count axes need cleanup or a limit raise. |
RATE_LIMITED |
429 | Yes, with backoff | Too many requests. |
INTERNAL_ERROR |
500 | Maybe | Unexpected server error. request_id is the support handle. |
Job / render codes#
Returned inside a job's result_json (and the completion webhook payload) or as the code of a 500 when a sync-wrapped call fails.
| Code | Retriable? | Meaning |
|---|---|---|
RENDER_FAILED |
Sometimes | The render worker failed. Message carries the worker-level cause below. |
INGEST_FAILED |
Sometimes | Ingestion failed (corrupt upload, unsupported inner structure). |
INSTANTIATE_FAILED |
Sometimes | Template instantiation failed. |
PREVIEW_FAILED |
Sometimes | Template/document preview failed. |
WORKER_FAILED |
Yes | The worker died mid-job (infra). Safe to retry. |
Worker-level causes#
These appear inside RENDER_FAILED messages. They identify the exact stage that broke:
| Code | Meaning |
|---|---|
TYPE_MISMATCH |
Spec type doesn't match the renderer invoked (internal routing bug — report it). |
INVALID_ELEMENT |
An element is structurally invalid (e.g. heading.level out of 1–6). |
UNSUPPORTED_ELEMENT |
Element type unknown to this renderer. |
UNSUPPORTED_IMAGE_FORMAT |
Image bytes are not a supported raster format. |
UNRESOLVED_ASSET |
An asset:// ref reached the renderer unresolved (internal — report it). |
INVALID_CHART_DATA |
Chart data shape doesn't match the chart kind. |
OOXML_POSTPROCESS_ERROR |
Native chart/font injection into the OOXML zip failed. |
READ_ERROR / STYLES_READ_ERROR / MASTERS_READ_ERROR |
Worker I/O on spec/compiled-theme inputs failed (infra). |
RUNTIME_ERROR |
Uncaught renderer error — report with the request_id. |
Theme + template specifics#
| Situation | Code | Notes |
|---|---|---|
| Unknown theme in create/spec | VALIDATION_FAILED (422) |
Message lists the themes visible to your tenant. Omit theme to get office. |
| Theme registration doesn't compile | VALIDATION_FAILED (422) |
Nothing was saved — fix and re-PUT. |
| Deleting a builtin theme | FORBIDDEN (403) |
Builtins can't be deleted; tenant themes shadowing them revert on delete. |
| Missing template variable | warning, not error | PPTX/XLSX render empty + TEMPLATE_VARIABLE_MISSING fidelity warning; DOCX errors (docx-templates is strict). Use placeholder_schema from the template listing to validate fills first. |
| Template expression not allowed | warning | TEMPLATE_EXPRESSION_ERROR; the expression renders empty. |
Batch patch atomicity#
PATCH /v1/documents/{doc_id} with multiple operations is transactional: operations validate and apply in order against an in-memory copy, and the new spec version is committed only when every operation succeeds. A failing operation (422) leaves the document exactly as it was — there are no half-built documents. Re-submit the whole corrected batch.
Fidelity warnings (not errors)#
Ingestion and rendering degrade gracefully: anything lossy emits a structured fidelity warning (INGEST_*, NATIVE_FALLBACK, TEMPLATE_*) in the fidelity.warnings[] array with a severity, never a silent drop. See Ingestion + fidelity.