Error format
Every error shares one flat envelope:
{
"error": "validation_failed",
"message": "validation failed",
"fields": {
"slug": "slug is required",
"outputOptions.pdf.format": "format \"A9\" is not supported (allowed: A0, A1, …)"
}
}
fields is present only for field-level validation errors. Common codes:
| HTTP | error code | When |
|---|---|---|
| 400 | kind_mismatch | Endpoint doesn't match the active template kind. |
| 400 | invalid_json | Request body isn't valid JSON (or is empty when required). |
| 400 | name_mismatch | PUT template: filename in the body doesn't match the URL. |
| 403 | csrf_blocked | Sec-Fetch-Site: cross-site on a mutating call. |
| 404 | not_found | Report, template, or version doesn't exist. |
| 409 | duplicate_slug | A report with that slug already exists. |
| 413 | upload_too_large | Template upload exceeds MAX_BINARY_UPLOAD_BYTES. |
| 415 | unsupported_media_type | Body present with an unsupported Content-Type. |
| 422 | validation_failed | Field validation failed (see fields). |
| 422 | invalid_template_name | Asset name has illegal characters or hits a reserved name. |
| 422 | invalid_template | Uploaded content is invalid — bad UTF-8 HTML, or not a real .docx/.xlsx. |
| 422 | template_missing | Render/preview called with no active template selected. |
| 422 | html_preview_unavailable | preview-html called on a non-HTML active template. |
| 422 | empty_template | The rendered output was empty. |
| 422 | template_error | Handlebars failed to compile/execute (also covers JS helper errors). |
| 422 | empty_commit | A commit would record zero changed files. |
| 500 | internal_error | Unexpected server error. |
| 503 | *_renderer_unavailable | The PDF/DOCX/XLSX renderer isn't configured on the server. |
| 503 | versions_unavailable | Commit/history store not configured. |