Errors & recovery

Recover the resource, not just the request.

Never parse a message string for control flow. Preserve the HTTP status,error.code, retryable, request ID, and any safe SDK recovery context such as document ID or idempotency key.

On this page

Find your error code

Select the exact error.code to jump to its recovery row. Expand that row’s code-specific guidance for its meaning. No response or code? Use the transport and SDK scenarios below.

Terminal processing error codes

These codes arrive on a failed document. The document is already terminal; retrying a GET or confirmation does not restart it. They are distinct from a local SDK timeout while work continues.

Code not listed? Use the unknown-code guidance.

Recovery boundaries

A needs_review result is not a transport failure to retry. When required fields, line-item acceptance or duplicate checks cause review, inspect the returned findings and the document’s review policy settings.

What happenedRetry?Identity and bytesResource / billing
Invalid request fields
  • invalid_request

Correct the rejected fields before retrying; no blind retry.

Code-specific guidance
invalid_request
Request fields or query parameters did not validate.
Inspect error.details.issues when present. A rejected create may be corrected; if a document already exists, recover its original identity instead of changing the body behind its key.This is request validation, not proof that uploaded bytes are corrupt. Preserve any known document ID.
Invalid callback URL
  • invalid_callback_url

Correct or omit the optional callback URL before a valid create.

Code-specific guidance
invalid_callback_url
The optional callback destination was rejected.
Use an allowed public HTTPS destination without credentials or a fragment. Do not mutate a create body already associated with an existing document and idempotency key.The callback was rejected; this does not diagnose the source file. Callback configuration cannot be repaired by re-uploading bytes.
Invalid API key or forbidden operation
  • invalid_api_key
  • forbidden

No automatic retry.

Code-specific guidance
invalid_api_key
The supplied API key was not accepted.
forbidden
The account or credential is not permitted to perform this operation.
Fix the credential or account authorization. Do not send invoice bytes.The rejected request creates no usable resource; an earlier known document may still exist.
Billing required or Trial allowance exhausted
  • billing_required
  • usage_limit_exceeded

Recover entitlement first. Create retries use the exact body/key; upload-complete retries the same document.

Code-specific guidance
billing_required
No usable processing entitlement. Synchronous confirmation can resume after recovery; a terminal async rejection cannot.
usage_limit_exceeded
The complete document does not fit the active Trial allowance; upgrade before a deliberate new attempt.
Never re-PUT after upload-complete billing recovery. A terminal async rejection cannot be resumed; any new submission is a deliberate new document with a new stable key.Pre-provider rejection is non-billable. Preserve the document ID; Trial never partially processes a document to fit its allowance.
Source exceeds the size limit
  • document_too_large

Provide a supported source no larger than 20 MiB; do not retry unchanged oversized bytes.

Code-specific guidance
document_too_large
The declared or stored source exceeds the 20 MiB maximum.
Declare the exact byte count. If an oversized object is already stored at an immutable upload path, use a new document for the corrected source; never overwrite it.A size rejection is not a page-limit or remaining-Trial-allowance decision.
Unsupported or mismatched content type
  • unsupported_content_type

Use PDF, JPEG, or PNG with the matching MIME type.

Code-specific guidance
unsupported_content_type
The declared MIME type is unsupported, or the stored type does not match an allowed declaration.
At create, correct the rejected declaration. At upload-complete, a wrong-MIME object already at the immutable path requires a new document, not an overwrite or a changed declaration.Changing a filename or MIME label does not convert unsupported bytes into a supported document.
Invalid, unsupported, corrupt, or immutable wrong-metadata input
  • upload_size_mismatch
  • invalid_document
  • corrupt_pdf
  • encrypted_pdf
  • unsupported_document_type
  • multiple_invoices_detected

Do not retry unchanged invalid bytes. Correct the source or immutable metadata mismatch first.

Code-specific guidance
upload_size_mismatch
The stored source size differs from the declaration; use a new document with the correct bytes and byte count.
invalid_document
The document is invalid; after inspection, its bytes/signature are not a supported PDF, JPEG, or PNG.
corrupt_pdf
The PDF is corrupt; obtain a valid export before a new submission.
encrypted_pdf
The PDF is encrypted; provide an unencrypted copy you are authorized to process.
unsupported_document_type
The content is not a supported invoice; changing its MIME label does not make it one.
multiple_invoices_detected
The source contains multiple distinct invoices; submit each complete invoice separately, including when invoices share a page.
Wrong size or MIME at the immutable upload path needs a new document. Corrupt or unsupported content cannot be repaired by retry. A terminal failed document remains failed.No usable result; documented pre-provider rejection is non-billable. New corrected bytes need their own logical submission and stable key.
Upload capability expired
  • upload_expired

Reject the stale signed capability. An API upload_expired response must not be retried as if its reservation can be refreshed.

Code-specific guidance
upload_expired
The API rejected the expired upload reservation or upload timing; this is not merely an expired signed URL.
If only the signed URL expired while the reservation is still valid, replay create with the exact body/key. Only an authoritative expiry permits a deliberate new logical submission; never rotate keys just because a request timed out.The old capability is unusable; no replacement resource is implied. A 200 awaiting_upload create replay must probe upload-complete before any PUT.
Upload reported not complete
  • upload_not_complete

A complete PUT may be retried only while the signed capability is valid.

Code-specific guidance
upload_not_complete
The expected source object is absent; this authoritative response permits a valid complete PUT.
The authoritative response says bytes are absent. Send only returned upload headers; never API credentials.Reuse the same document and upload path; no second create.
Idempotency conflict
  • idempotency_conflict

Do not retry a changed body behind the same key.

Code-specific guidance
idempotency_conflict
The same live key was presented with a different create identity.
Restore the original create body, or use a new key only for a genuinely new logical invoice submission.The original identity may already own a resource; conflict itself is not billable.
Operation does not fit the document state
  • invalid_document_state

Retrieve the same document and choose the operation allowed by its current status.

Code-specific guidance
invalid_document_state
The requested operation is not valid for the current document state.
Preserve the document ID. Do not infer that the source is absent, re-PUT, or create a replacement from this code alone.Processing or a terminal result may already exist. A failed document does not restart when polled.
Rate limit or temporary service unavailability
  • rate_limit_exceeded
  • service_unavailable

Retry the same operation finitely when retryable; treat Retry-After as a minimum delay.

Code-specific guidance
rate_limit_exceeded
Request rate was limited; wait at least Retry-After before a bounded retry.
service_unavailable
The service is temporarily unavailable; retry only within the operation’s identity and retry rules.
Keep the same create body/key or confirmation document. Never turn a confirmation retry into a PUT.A resource may already exist; preserve recovery context. A 5xx alone does not authorize retry when retryable is false.
Internal request failure
  • internal_error

No automatic retry when retryable is false. Do not infer retry permission from HTTP 500; contact support with the request ID if needed.

Code-specific guidance
internal_error
An internal failure occurred. Do not infer retry permission from HTTP 500; inspect retryable and preserve the request ID.
Preserve the document ID and exact create body/key. A failed response does not prove that no work occurred; never replace the document or re-PUT without the documented recovery step.An earlier resource or processing run may still exist. Follow documented same-resource recovery only when retryable permits it.
Ambiguous create transport outcome

Retry the exact create body and idempotency key.

Never rotate the key merely because the response was lost or timed out.The logical document may already exist.
Ambiguous signed PUT outcome

Probe upload-complete before any second PUT.

Re-PUT only after authoritative upload-not-complete and only with a still-valid capability.Reuse the same document; uploaded bytes may already be present.
Ambiguous upload-complete outcome

Retry or probe only the same document confirmation.

Do not re-PUT and do not create a replacement document.Processing may already be queued or terminal.
SDK cancellation or polling timeout

The SDK stops waiting; server-side work is not cancelled by assumption.

Use safe document/idempotency recovery context to resume authenticated GET or the documented operation.The known server document may still finish and be billable normally.
Expired result or authoritative not found
  • document_not_found
  • document_expired

Do not reinterpret either response as a successful DELETE or completed result.

Code-specific guidance
document_not_found
No document is available to this account under that ID; never treat this as DELETE success.
document_expired
The retained result has expired; it cannot be retrieved again.
Check the document ID and account. Persist results before result_expires_at; expired content cannot be recovered by retry. A real 404 remains authoritative.No accessible retained document result was returned; no new resource is implied.
Requested usage period is unavailable
  • usage_period_not_found

Choose an existing retained closed period, or omit periods_ago for current usage.

Code-specific guidance
usage_period_not_found
The requested retained closed billing period does not exist for the account.
Keep the account context. This is a usage-query error; do not resubmit or delete an invoice.The requested historical period does not exist for this account. It does not mean a document was deleted or usage was zero.
Terminal processing failure or timeout
  • document_processing_failed
  • processing_timeout
  • ocr_failed
  • semantic_extraction_failed

The document is already terminal failed; polling does not restart it. Follow retryable and documented recovery, and contact support with safe identifiers if needed.

Code-specific guidance
document_processing_failed
Processing ended without a usable result.
processing_timeout
Server processing exceeded its permitted lifetime; this does not identify a particular internal stage.
ocr_failed
Document text/layout processing failed; no usable result was produced.
semantic_extraction_failed
Structured invoice extraction failed; no usable result was produced.
Do not automatically rotate the key or re-PUT. If a new attempt is appropriate, submit it deliberately as a new logical document with a new stable key.No usable result; genuine processing failures are non-billable. A processing_timeout is different from a local SDK polling timeout.
Page, complexity, or result-size limit
  • document_page_limit_exceeded
  • document_complexity_limit_exceeded
  • result_too_large

Do not blindly repeat the same source. Check the applicable limit and use a supported representation of one complete invoice, or seek help.

Code-specific guidance
document_page_limit_exceeded
The source exceeds the 20-page limit.
document_complexity_limit_exceeded
The invoice exceeds supported extraction complexity, such as the line-item limit.
result_too_large
The structured result exceeds the supported result-size limit; changing upload MIME or plan does not repair it.
The failed document is terminal. Do not split one invoice into fragments or omit invoice content to fit a limit. Any suitable replacement is a deliberate new submission.No usable result; product limit failures are non-billable. Paid overage or a larger plan does not remove document limits.

Unknown future diagnostic codes

Keep the unknown non-empty code for display and diagnostics. For a synchronous API error, fall back to HTTP status, retryable, and generic documented recovery. For validation checks, fall back to check status/severity, paths, and validation.review_required. An unknown async error still leaves the document terminal failed.

Return to the error-code lookup

Thrown error versus terminal failed

A terminal failed document is returned normally by wait and process. SDK-local cancellation, timeout, invalid response, or a synchronous API error is thrown. A polling timeout leaves server-side work running; callers can resume GET with the known document ID.

Callbacks are untrusted wakeup hints

  1. Receive document.finished.
  2. Parse its event and document IDs only as hints.
  3. Fetch the document with an authenticated GET.
  4. Require fetched callback.event_id to equal the received event ID, then act on the fetched document.

MVP callbacks are unsigned and have no persistent webhook endpoint management. A receiver should fetch promptly and persist only the downstream representation it needs.

Avoid secrets or personal data in callback URLs: Vercel may retain destinations in platform logs. Resume URLs can themselves be secret; use polling if that retention is unsuitable. See the retention limits.

Result retention and deletion

Temlavo is not a long-term invoice archive. Terminal structured results are retained 7 days by default; processing.result_expires_at is authoritative. After expiry, 410 document_expired is an expected lifecycle outcome. Explicit DELETE ends document API access and clears stored results and document fields. Storage deletion is attempted immediately and retried if needed. The separate account-lifetime discovery index of raw accounting-entity IDs remains, as do required financial/security records. Document DELETE does not close an account or delete Vercel platform logs. See the Privacy Notice's retention and account-closure details.

Your own database, callback handler, CLI output, CI logs, and n8n execution history are outside Temlavo retention and deletion control.

Support and debugging

Preserve the safe X-Request-Id, document ID, and idempotency key when asking for help. Never send the API key, signed upload capability, source invoice, full result, or provider details in an initial support report.

Contact support with the safe identifiers above and a short description of the issue.