Errors
Docs index
Every code the API can return, what it means, and what to do about it.
Branch on the code, not the status
Failures return a machine code alongside the HTTP status. Branch on the code: the status says what kind of problem it is, and the code says which one. The Status column below is filled where one route owns a code; where it is blank the same code is returned with different statuses by different operations, and the authoritative status per operation is in the OpenAPI document under the response it sits in.
Note A 503 means the work did not start. A 409 means the request was understood and the state refused it — those are different retries. A 429 means the work is allowed and the window is full: honour Retry-After where it is sent, and otherwise wait for the next clock minute rather than retrying immediately.
Authentication, scope and plan
Everything that can refuse a request before it reaches the work.
| Code | Status | Meaning | What to do |
|---|---|---|---|
CONNECTION_ID_INVALID | 400 | The connection id was not a UUID. | Use the id from GET /connections. |
OAUTH_CONNECTION_ID_INVALID | 400 | The OAuth connection id was not a UUID. | Use the id from GET /oauth-connectors. |
API_KEY_ID_INVALID | 400 | The key id was not a UUID. | Use the key id shown in Workspace → Developers. |
API_KEY_INPUT_INVALID | 400 | The rotation body did not validate. | Check the request schema for the operation. |
MANIFEST_DIGEST_INVALID | 400 | The manifest digest did not match sha256:<64 hex>. | Pass the digest exactly as the World reported it, prefix included. |
SOURCE_IDEMPOTENCY_KEY_INVALID | 400 | x-tavonel-source-idempotency-key was present and was not 64 hex characters. | Send a sha256 hex digest, or omit the header entirely. |
QUESTION_INVALID | 400 | The question was absent, or shorter than the minimum. | Send a question between 3 and 500 characters. |
QUESTION_TOO_LARGE | 413 | The question exceeded 500 characters. | Shorten it. Ask is a question, not a document. |
QUERY_INVALID | 400 | The search query was absent, or shorter than the minimum. | Send a query between 3 and 500 characters. |
QUERY_TOO_LARGE | 413 | The search query exceeded 500 characters. | Shorten it. |
RETRIEVAL_QUESTION_INVALID | 400 | The retrieval runtime refused the question text itself. | Send a plain question; control characters and empty strings are refused. |
WORLD_PAGE_LIMIT_INVALID | 400 | limit was outside 1–50. | Use a limit inside 1–50, or omit it to read the whole lens. |
WORLD_PAGE_CURSOR_INVALID | 400 | The cursor named an id this lens does not contain. A wrong cursor is refused rather than answered with an empty page, so a paging bug is visible instead of silent. | Restart from the first page. The cursor is the last item id from the previous page, keyset — not an offset. |
WORLD_LENS_NOT_PAGEABLE | 400 | history, files and review return whole; limit and cursor are refused on them. | Drop the paging parameters for those three lenses. |
WORLD_PROMOTION_INVALID | 400 | The activation request body did not validate. | Activation is a signed-in browser action; no API key holds it. |
WORLD_ROLLBACK_INVALID | 400 | The rollback request body did not validate. | Rollback is a signed-in browser action; no API key holds it. |
PROMOTION_METADATA_TOO_LARGE | 413 | The activation note exceeded its bound. | Shorten the note. |
ROLLBACK_METADATA_TOO_LARGE | 413 | The rollback note exceeded its bound. | Shorten the note. |
CONNECTION_INPUT_INVALID | 400 | The connection body did not match ConnectionInput. | Check the schema: provider, mode, displayName and configuration are required and secretReference must be null. |
CONNECTION_BATCH_INVALID | 400 | The sync batch did not match ConnectionBatch. | Check the schema. Every event needs kind, nativeId, revision, contentSha256, sizeBytes, mimeType, documentId and sourceIdempotencyKey, each nullable where the schema says so. |
OAUTH_CONNECTOR_INPUT_INVALID | 400 | The authorization body did not match OAuthConnectorAuthorizationInput. | Send a supported provider and a displayName. |
OAUTH_SYNC_INPUT_INVALID | 400 | The OAuth connection sync body did not validate. | Check the schema for the operation. |
AUDIT_EXPORT_WINDOW_INVALID | 400 | The audit export window was not a range TAVONEL serves. | Narrow the window. |
Documents and intake
What stops a file before it becomes a source — including the two ceilings the deployment actually enforces.
| Code | Status | Meaning | What to do |
|---|---|---|---|
COMPLETED_READ_INVALID_OR_DISABLED | 503 | The internal settlement carried completed-read facts while certification was disabled, or the facts conflicted with the settlement scope or outcome. | Preserve the stored OCR and retry the same settlement after the configuration or fact mismatch is resolved. |
COMPLETED_READ_REQUIRED | 503 | Completed-read certification was enabled, but a successful OCR settlement omitted its required persisted-read facts. | Recover the facts from the existing persisted OCR and retry the same settlement without another OCR call. |
COMPLETED_READ_DISABLED | 503 | The completed-read settlement helper refused certification because its rollout flag was disabled. | Preserve the pending settlement and resolve the worker/server configuration mismatch before retrying. |
COMPLETED_READ_INVALID | 503 | The completed-read settlement helper could not validate the exact receipt shape, object keys, identities, digests or observed page count. | Recover the original persisted-read facts and correct the mismatch before retrying the same settlement. |
COMPLETED_READ_DIRECT_UPLOAD_REQUIRED | 503 | The current source scope could not be established as a confirmed direct upload; connector sources cannot receive completed-read certification. | Check durable upload admission and source scope. Do not certify connector or unexplained source origins. |
COMPLETED_READ_SETTLEMENT_FAILED | 503 | The completed-read transaction failed or its response did not acknowledge the exact successful reservation settlement and immutable proof. | Retry the identical persisted-read facts to reconcile an uncertain commit. Do not fall back to legacy settlement. |
INTAKE_TRIAGE_REQUIRED | varies | The request has no completed server-owned triage receipt for the selected intake set. | Run source triage, review the whole set and continue with its returned receipt. |
TRIAGE_COMPLETE_BODY_INVALID | varies | The request to complete triage did not identify a valid staged member and preflight approval. | Use the stage and preflight identifiers returned for this batch. |
INTAKE_TRIAGE_STAGE_RECEIPT_INVALID | varies | The server could not prove the staged member belongs to the expected triage receipt. | Recover the same batch from the server before retrying completion. |
INTAKE_TRIAGE_SEAL_RETRY_REQUIRED | 409 | The staged object could not be proven sealed into its immutable quarantine version. | Reconcile the same triage member and retry only after its seal state is known. |
TRIAGE_PREFLIGHT_BODY_INVALID | varies | The preflight request did not contain a valid batch identity and complete set of choices. | Review the full batch and submit its supported choices again. |
TRIAGE_RECEIPT_BODY_INVALID | varies | The receipt request did not identify a valid batch, preflight approval and set of choices. | Use the identifiers returned by triage and submit the complete reviewed set. |
INTAKE_TRIAGE_BATCH_INCOMPLETE | 409 | The server has not received every expected member of this triage batch. | Finish staging the complete batch before requesting its receipt. |
INTAKE_TRIAGE_PREFLIGHT_INCOMPLETE | 409 | The server has no complete preflight approval for the triage batch. | Run preflight on the entire batch and review its returned maximum. |
TRIAGE_NO_FILES_SELECTED | 409 | The reviewed triage receipt contains no files approved for intake. | Select at least one eligible file, or stop this intake attempt. |
TRIAGE_STAGE_BODY_INVALID | varies | The request to stage triage files did not contain a valid batch and file list. | Use a valid batch identity and submit supported files within the stated limits. |
TRIAGE_STAGE_FILE_INVALID | varies | A file in the triage staging request failed its identity, type or size checks. | Review that file's reported error and select a supported file before retrying. |
TRIAGE_STAGE_PARTIAL | varies | At least one requested file failed staging; the response may also identify files that were staged successfully. | Inspect every per-file result and reselect any member that did not stage. |
TRIAGE_CHOICES_REQUIRED | 409 | The triage receipt did not include one supported include or exclude choice for every reviewed file. | Review every listed item and submit an include or exclude choice for the complete set. |
INTAKE_TRIAGE_ROLLOUT_DISABLED | 503 | The coordinated file triage workflow is not enabled. | Retry only after the triage client, server and versioned storage contract are deployed together. |
INTAKE_RETRIAGE_REQUIRED | 409 | The saved triage receipt is missing, stale or inconsistent with the approved member and current configuration. | Review and approve a fresh complete-set triage receipt before continuing. |
INTAKE_TRIAGE_OBJECT_NOT_SEALED | 409 | The server cannot prove the triage upload was sealed into the required immutable quarantine object. | Reconcile the same member and retry only after the server confirms its sealed state. |
INTAKE_TRIAGE_OBJECT_CHANGED | 409 | The quarantine object no longer matches the approved triage member's size, type or immutable version. | Do not confirm this object; reconcile the approved member or review a fresh intake. |
INTAKE_APPROVAL_INVALID | 400 | The approval manifest or attempt identity was malformed or exceeded the supported complete-set bounds. | Reselect the complete file set and review the new maximum before approving it. |
INTAKE_APPROVAL_DUPLICATE_FILE | 400 | The manifest repeated a stable file identity, so the server refused to create an ambiguous approval. | Reselect the complete set; do not submit duplicate entries. |
INTAKE_APPROVAL_MIME_NOT_NORMALIZED | 400 | The approved MIME value does not exactly match the server-normalized file type. | Use the MIME type and filename pair shown by the supported formats list. |
INTAKE_APPROVAL_MANIFEST_MISMATCH | 400 | The manifest digest does not match the complete file metadata the browser submitted. | Reselect and hash the whole set again, then approve its current maximum. |
INTAKE_APPROVAL_UNKNOWN_CEILING_REQUIRED | 503 | The server could not preserve the full per-file processing ceiling for an uncounted format. | Retry after the intake configuration is corrected; no lower maximum was approved. |
INTAKE_APPROVAL_AGGREGATE_EXCEEDED | 409 | The approved aggregate maximum exceeds a server-enforced bound. | Review a fresh whole-set quote and approve only its exact maximum. |
INTAKE_APPROVAL_AGGREGATE_MISMATCH | 409 | The server's recomputed maximum differs from the amount the customer approved. | Review the returned maximum and explicitly approve the refreshed quote. |
INTAKE_APPROVAL_CONFLICT | 409 | The same attempt key was reused for a different file set, quote or pricing fingerprint. | Reselect the exact original files to recover, or review and approve the changed complete set under a new attempt. |
INTAKE_APPROVAL_FILE_OUT_OF_SCOPE | 409 | A requested file is not a member of this server-held approval. | Reselect the exact approved set and retry with its saved attempt identity. |
INTAKE_APPROVAL_REQUIRED | 428 | The upload operation has no valid customer-approved attempt identity. | Review and approve the complete set's maximum before requesting upload capabilities. |
INTAKE_APPROVAL_DISABLED | 404 | Whole-set intake approval is not enabled yet; uploads reserve and confirm one file at a time. | Request an upload capability per file without an attempt identity. |
INTAKE_APPROVAL_LINEAGE_UNAVAILABLE | 503 | The database does not have the approval functions this request needs, so nothing was approved, reserved or confirmed. | Retry after the intake approval migrations are applied; the attempt is unchanged. |
INTAKE_APPROVAL_SCOPE_MISMATCH | 409 | The document, content digest, file identity or scope differs from the approved manifest. | Reselect the exact approved file and recover that attempt; changed content requires a new approval. |
INTAKE_APPROVAL_RESERVATION_EXPIRED | 409 | The approved member's processing reservation expired before the capability operation completed. | Recover the attempt and request a newly reviewed quote and approval. |
INTAKE_APPROVAL_CANCEL_INVALID | 400 | The cancellation request did not identify one valid approved member. | Recover the saved attempt and submit its exact member identity. |
COMPUTE_LEDGER_NOT_CONFIGURED | 503 | The approved-intake ledger is not configured, so this request could not read or write durable approval state. | Retry after ledger configuration is restored, recovering the same attempt before creating another. |
INTAKE_APPROVAL_LEDGER_FAILED | 503 | The approved-intake ledger could not complete a durable operation; its commit status may be uncertain. | Read the same attempt to recover its committed state before retrying. |
INTAKE_APPROVAL_RECEIPT_INVALID | 503 | The ledger response did not prove the expected approved member identity or state. | Recover the same attempt from the server before retrying or compiling. |
INTAKE_PRICE_STALE | 409 | Pricing changed after the customer reviewed the quote, so the former maximum cannot authorize this intake. | Review the refreshed maximum and approve again. |
INTAKE_CONFIRMATION_FAILED | 503 | The atomic admission and approval confirmation could not be completed. | Recover the same attempt to determine whether confirmation committed before retrying. |
INTAKE_CONFIRMATION_NOT_CONFIGURED | 503 | The confirmation database connection is not configured. | Retry after the service configuration is restored; do not create a replacement attempt while this one is uncertain. |
INTAKE_CONFIRMATION_RECEIPT_INVALID | 503 | The database response did not prove that this approved member was atomically confirmed. | Recover the same attempt from the server before retrying or compiling. |
QUARANTINE_ADMISSION_NOT_FOUND | 409 | No matching intake admission exists for the approved document. | Recover the attempt or restart by reviewing a fresh complete-set maximum. |
QUARANTINE_OBJECT_NOT_FOUND | 409 | The uploaded object is absent, so confirmation or release cannot proceed as requested. | Retry the same approved member and recover its state before starting another attempt. |
INVALID_SOURCE_DIGEST | 400 | The submitted content digest is not a valid SHA-256 identity. | Hash the exact selected bytes again and retry the same approved attempt. |
OBSERVED_MIME_MISMATCH | 409 | The stored object's observed MIME type differs from the approved type. | Choose a file whose content and filename match a supported format, then approve the new complete set. |
UPLOAD_CONFIRM_BODY_INVALID | 400 | The confirmation request did not identify a valid approved document. | Recover the saved attempt and submit the exact approved member identity. |
UPLOAD_CONFIRM_REQUEST_TOO_LARGE | 413 | The confirmation metadata exceeded the endpoint's bounded request size. | Retry with the supported attempt and member fields only. |
UPLOAD_RELEASE_BODY_INVALID | 400 | The release request did not identify a valid approved document. | Recover the saved attempt and submit the exact approved member identity. |
UPLOAD_RELEASE_REQUEST_TOO_LARGE | 413 | The release metadata exceeded the endpoint's bounded request size. | Retry with the supported attempt and member fields only. |
UPLOAD_ALREADY_STORED | 409 | The release endpoint found the object in storage, so the approved member was not released. | Confirm the same approved member; do not start a replacement attempt. |
QUARANTINE_LIST_UNAVAILABLE | 503 | The listing of sources that were refused or are not yet prepared could not be read. No inventory is returned rather than one that silently leaves those sources out. | Retry. Nothing was changed; if it keeps failing, contact TAVONEL with the time of the request. |
AUTH_REQUIRED | 401 | No credential was presented, or the bearer token is not a key TAVONEL issued. This is what an unauthenticated request to any scoped route returns. | Send Authorization: Bearer <key>. Keys are created in Workspace → Developers and the plaintext is shown once; a key you cannot find again is rotated, not recovered. |
API_KEY_INVALID | varies | The bearer token was well-formed but did not match a stored key. | Check you are sending the whole key, including the tvnl_live_ prefix, and that it belongs to TAVONEL. |
API_KEY_EXPIRED | varies | The key matched and its expiry has passed. | Rotate it: POST /developer/keys/{id}/rotate in a signed-in session returns a replacement once. |
API_KEY_REVOKED | varies | The key matched and was revoked. A rotation revokes the key it replaces. | Use the replacement key from the rotation, or mint a new one. |
API_SCOPE_REQUIRED | 403 | The key authenticated and does not carry the scope this operation requires. The request was refused rather than answered with less. | Mint a key carrying the scope named in the operation's x-tavonel-scope. Scopes are fixed at creation; a key is not widened in place. |
REMOTE_MCP_COHORT_EXCLUDED | 403 | The workspace is valid and is not in the remote MCP pilot cohort. The remote MCP endpoint (consent, token and every call) is open to that cohort only. | Nothing a caller can send fixes this. Access is arranged with us — write to support@tavonel.com. |
REMOTE_MCP_COHORT_CONFIG_INVALID | 503 | The deployment's remote MCP pilot cohort is unset, malformed or wider than the canary allows, so the surfaces it gates (the remote MCP, and Ask while signed receipts are on) admit nobody rather than everybody. | Nothing a caller can send fixes this. It is an operator configuration; retry later. |
PILOT_ACCESS_REQUIRED | 403 | The credential is valid and the workspace it names is not admitted to TAVONEL. | Nothing a caller can send fixes this. Access is arranged with us — write to support@tavonel.com. |
WORKSPACE_MEMBERSHIP_REQUIRED | 403 | The user is authenticated but has no active durable membership in the requested workspace. | Accept a valid workspace invitation, or ask a workspace owner to restore membership before retrying. |
API_KEY_AUTHORIZATION_REVOKED | 403 | The API key was issued under an older membership authority revision and cannot regain access after that grant changes. | Create a new key after the current membership is confirmed; an old key cannot be revived. |
AUTHORIZATION_CHANGED_RETRY | 403 | The caller's authorization changed while the request was in flight, so the request was abandoned rather than finished under a permission that may no longer hold. | Retry once. A second occurrence means the permission really was removed. |
SUBSCRIPTION_REQUIRED | varies | The workspace has no plan that includes this operation. | See /pricing for which plan includes it. |
STUDIO_SUBSCRIPTION_REQUIRED | 402 | The operation needs the higher plan tier — activation, rollback and retrieval-index rebuild are the three. | See /pricing. The bar is the same for all three on purpose: a plan that may activate and may not rebuild would leave its own Worlds answering from the fallback. |
SELF_SERVICE_NOT_ENABLED | varies | Self-serve purchase is not open today. | Nothing a caller can send changes it. Access is arranged with us. |
GPU_CREDITS_REQUIRED | varies | The workspace has no processing balance left to reserve against. | Add pages, or wait for the next grant. Nothing was charged. |
Rate and concurrency
The two limits the deployment enforces, and the one case where a refusal means the limit could not be read.
| Code | Status | Meaning | What to do |
|---|---|---|---|
API_RATE_LIMITED | 429 | The key has used its per-minute allowance for this scope. The window is a fixed clock minute per key and scope; the allowances are on /docs/billing-and-limits. | Wait for the next clock minute and retry. No Retry-After header is sent today, so back off on your own clock — a fixed one-minute wait is enough by construction. |
API_RATE_LIMIT_UNAVAILABLE | 503 | The allowance could not be read, so the request was refused rather than run unbounded. | Retry. This is fail-closed behaviour, not a limit you hit. |
ACTIVATION_RATE_LIMITED | 429 | The workspace has used its hour's allowance of World activations, rollbacks or retrieval-index rebuilds. Nothing was charged. | Honour the Retry-After header — it carries the seconds until the oldest one leaves the window — rather than retrying immediately. |
ACTIVATION_RATE_LIMIT_UNAVAILABLE | 503 | That hourly allowance could not be read, so the request was refused rather than run unbounded. | Retry. This is fail-closed behaviour, not a limit you hit. |
INTAKE_RATE_LIMITED | 429 | Too many upload capabilities were requested in the window. | Honour Retry-After (60 seconds) and retry. |
INTAKE_DAILY_QUOTA_EXCEEDED | 429 | The workspace's daily intake quota is spent. | Honour Retry-After (3600 seconds); the quota rolls with the day. |
WORKSPACE_CONCURRENCY_LIMIT | 429 | The workspace already has as many compiles in flight as it may. | Wait for one to settle. Poll GET /compile-jobs to see which. |
COMPILE_JOB_WORKSPACE_LIMIT_REACHED | varies | The workspace is at its compile-job ceiling. | Let running jobs settle before starting another. |
WORKSPACE_CACHE_CAPACITY_LIMIT | varies | The workspace's cached working set is full. | Retry after current work settles. |
Request shape
Refusals decided from the request alone, before any state is read.
| Code | Status | Meaning | What to do |
|---|---|---|---|
INVALID_JSON | 400 | The body was not parseable JSON. | Send valid JSON and content-type: application/json. |
NOT_JSON | 400 | The request did not declare a JSON body. | Set content-type: application/json. |
METADATA_ONLY_ENDPOINT | 415 | Document bytes were POSTed to a route that accepts only metadata. Bytes go direct to storage, never through the application server. | Request an upload capability and PUT the bytes to the URL it returns. |
REQUEST_TOO_LARGE | 413 | The JSON body exceeded the route's bound. | Split the request. The bounds are per-route and stated in the operation. |
JSON_TOO_LARGE | 413 | A stored JSON object (ocr.json, ocr-review.json or a candidate) exceeded its read or write bound. The response, and a compile job's events, name the object, its bytes and the bound. | Nothing in the request changes it. Report it with the document or job id. |
UNQUALIFIED_INPUT | 400 | A required field was missing or was not of the declared type. | Check the request schema for the operation; the response names no field, so validate against the contract. |
LIMIT_INVALID | 400 | limit was outside the range the operation accepts. | Use a limit inside the bounds the operation declares. |
AUDIT_LIMIT_INVALID | 400 | The audit limit was outside its range. | Use a limit inside the declared bounds. |
RUN_ID_REQUIRED | 400 | The run id path segment was empty. | Supply the run id returned when the run was started. |
RESOLUTION_REQUIRED | 400 | A blocker resolution was requested with no resolution field. | Send one of continue, remove_blocked, retry_eligible. |
RESOLUTION_NOT_APPLIED | 409 | The resolution was understood and the job's state refused it. | Re-read the job: the blockers it is holding decide which resolutions are legal. |
COLLECTION_ID_INVALID | 400 | The collection id did not match collection-<32 hex>. | Use the id as returned, unmodified. |
WORLD_ID_INVALID | 400 | The World id did not match the collection id pattern. | Use the collection id as returned. |
CORPUS_ID_INVALID | 400 | The corpus id did not match corpus-<32 hex>. | Use the corpus id as returned. |
SOURCE_EXCEEDS_PROCESSING_CEILING | 413 | requestedBytes is above what every processor in the chain can read. The body carries maxBytes, maxPages and a limit sentence. This is the refusal the 5 MB per-source ceiling produces. | Split the document and upload the parts. Admitting a larger file would only move the refusal somewhere you cannot see it. |
SOURCE_TOO_MANY_PAGES | varies | The document decoded to more pages than the rasterizer renders. The page ceiling cannot be checked at intake, because intake deliberately never decodes the document, so this arrives after the bytes are stored rather than at the capability call. | Split the document. The page ceiling is published on /docs/files-and-formats and in the capability manifest's knownLimitations. |
SOURCE_TOO_LARGE | varies | A connected source's bytes are above the per-source ceiling. | Exclude it from the sync, or split it at the source. |
INTAKE_FILE_TOO_LARGE | varies | The admission ledger refused the size. Answered to the caller as SOURCE_EXCEEDS_PROCESSING_CEILING. | Split the document. |
INTAKE_DISABLED | 503 | Intake is closed today. | Nothing a caller can send opens it. /api/status publishes the current state. |
CUSTOMER_DATA_NOT_ENABLED_FOR_WORKSPACE | 403 | This workspace has no current approval to process its sources. | Accept the processing terms in the workspace before uploading or syncing files. |
INTAKE_IDEMPOTENCY_CONFLICT | 409 | The same source idempotency key was already used for different bytes. | Use a fresh key, or re-send the original bytes. |
UNQUALIFIED_DOCUMENT | 400 | The document id does not name a document in this workspace, or it is not in a state this operation accepts. | List documents and use an id from the response. |
UNQUALIFIED_MIME | 400 | The declared MIME type is not in the capability manifest. | Read GET /capabilities: a format absent from it is refused at upload rather than accepted and dropped. |
MIME_TYPE_UNSUPPORTED | 400 | Same refusal, raised by the qualifier. | Check GET /capabilities before uploading. |
FILENAME_MIME_MISMATCH | 400 | The extension and the declared MIME type disagree. | Declare the MIME type that matches the extension. |
FILE_NAME_INVALID | 400 | The filename carried a path separator or a character the store refuses. | Send a plain filename with no directory component. |
INVALID_FILENAME | 400 | Same refusal from the intake validator. | Send a plain filename. |
SIGNER_NOT_CONFIGURED | 503 | The upload URL signer is not configured, so no capability can be issued. | Nothing a caller can send. /api/status reports the deployment's state. |
SOURCE_VERSION_AMBIGUOUS | 409 | Two source versions carry the same identity and the request did not say which. | Name the version explicitly. |
SOURCE_NOT_QUALIFIED | varies | A connected source did not qualify for compilation. | Check the source's format against GET /capabilities. |
SOURCE_REVOKED | varies | The source's connection was revoked; its bytes are no longer reachable. | Reconnect the source, or drop it from the set. |
SOURCE_TOMBSTONED | varies | The source was deleted at origin and is recorded as gone rather than silently omitted. | Remove it from the compile set. |
SOURCE_DELETED | 409 | The uploaded source has a deletion tombstone, so its bytes cannot be admitted or served again. | Choose a different source; a deleted upload cannot be restored through this request. |
TRIAL_FILE_TOO_LARGE | 413 | Above the free-evaluation per-file bound, which is lower than the deployment ceiling. | The body carries maxBytes. Split the file, or move to a paid plan. |
TRIAL_ARCHIVE_NOT_INCLUDED | 402 | ZIP upload is not included in the free evaluation. | Upload the files individually, or move to a paid plan. |
TRIAL_FILE_LIMIT_EXCEEDED | varies | The free evaluation's file count is spent. | Move to a paid plan. |
TRIAL_PAGE_LIMIT_EXCEEDED | varies | The free evaluation's page allowance is spent. | Move to a paid plan. |
TRIAL_NOT_ACTIVE | varies | No free evaluation is active for this workspace. | Move to a paid plan. |
TRIAL_DISABLED | varies | Free evaluation is closed today. | Nothing a caller can send. |
TRIAL_CAPACITY_REACHED | varies | The deployment's concurrent free evaluations are full. | Retry later, or move to a paid plan. |
OCR_DAILY_SPEND_STOP | 503 | New document processing is paused for today by a safety limit on the deployment's own processing spend, not by your plan or your file. Documents already queued keep processing, and nothing was charged for this request. | Retry later. The limit lifts when the provider's next billing day opens, and the operator has been paged. |
OCR_SPEND_UNVERIFIED | 503 | New document processing is paused by a safety limit because today's processing spend could not be confirmed. Documents already queued keep processing, and nothing was charged for this request. | Retry later. The operator has been paged. |
TRIAL_FEATURE_NOT_INCLUDED | 402 | The operation is not in the free evaluation: creating, rotating or revoking an API key, and approving a remote MCP connection (which mints a key), among them. | Move to a paid plan. A free evaluation reads its World in the browser. |
TRIAL_LIMIT_REACHED | 402 | A free-evaluation bound is spent: its AI-access window, page, World or daily query bound, which Ask in the browser and World activation also read, or, with trial AI access enabled, its one live API key (hand-made, or minted by approving a remote MCP connection). | Revoke the existing key, wait for the next UTC day, or move to a paid plan. |
TRIAL_AI_ACCESS_CHECK_FAILED | 503 | The free evaluation's AI-access bounds could not be read, so nothing was allowed. | Retry; the check fails closed. |
REMOTE_MCP_INTERNAL_ERROR | 500 | A remote MCP tool failed inside the server for a reason that is not one of the API's own codes. The answer carries a request id instead of the failure's text. | Retry once. If it repeats, write to support@tavonel.com with the request id. |
REMOTE_MCP_REVOKE_NOT_AUTHORIZED | 401 | The operator's bulk revoke of remote MCP keys was called without the worker secret. | Operators only: send the worker secret as the bearer. |
API_KEY_AUDIENCE_INVALID | 401 | The token is a remote MCP connection's (tvnl_mcp_): it works only through the MCP endpoint, /api/mcp, never against the REST API directly. | Call the REST API with a key made in Workspace > Developers (tvnl_live_). |
ANSWER_SIGNING_UNAVAILABLE | 503 | Signed answer receipts are on for this workspace and no lifecycle signing key is usable, so the answer was withheld rather than sent unsigned. | Retry later. Nothing about the question needs to change. |
ANSWER_RECEIPT_MODE_INVALID | 503 | The deployment's answer-receipt mode is not one of off, shadow or on, so Ask refuses rather than guessing which. | Nothing a caller can send fixes this. It is an operator configuration; retry later. |
TRIAL_WORLD_LIMIT_REACHED | 402 | The free evaluation's one World is spent: a second compile, or activating a second World, is refused. | Move to a paid plan. |
TRIAL_DURABLE_COMPILE_REQUIRED | 402 | The free evaluation compiles through the durable job route only. | Use POST /compile-jobs rather than POST /collections/compile. |
TRIAL_SOURCE_REVIEW_REQUIRED | varies | A free-evaluation source was held for review by the risk gate. | Nothing automatic clears it. Write to support@tavonel.com. |
Compile
The document set, the job, and what a partial failure does.
| Code | Status | Meaning | What to do |
|---|---|---|---|
DOCUMENT_IDS_REQUIRED | 400 | The request carried no document id array. | Send documentIds with at least one id. |
DOCUMENT_SET_EMPTY | 400 | Nothing was selected to compile. | Send at least one document id. |
DOCUMENT_SET_UNQUALIFIED | 400 | A value in documentIds was not a document id. | Send UUIDs as returned by GET /documents. |
COLLECTION_ARTIFACT_SOURCE_DELETED | 409 | A document in this compile has been deleted, so its result is not stored. | Compile again without the deleted document. |
COLLECTION_ARTIFACT_SOURCE_BLOCKED | 409 | A connector source in this compile is suspended, tombstoned or no longer admitted, so its result is not stored. | Restore the connector's access, or compile without that source. |
COLLECTION_ARTIFACT_PROVENANCE_CONFLICT | 409 | This candidate key is already recorded against a different document set. | Nothing a caller can send. Report it with the collection id. |
COLLECTION_ARTIFACT_PROVENANCE_INVALID | 409 | The candidate's documents could not be recorded, usually because one id is not a UUID. | Compile documents by the UUIDs returned from GET /documents. |
COLLECTION_ARTIFACT_PROVENANCE_FAILED | 503 | The candidate's documents could not be recorded, so nothing was stored. | Retry. |
COLLECTION_ARTIFACT_PROVENANCE_NOT_CONFIGURED | 503 | The database is not configured, so no candidate can be recorded or stored. | Nothing a caller can send. |
COLLECTION_ARTIFACT_PUBLICATION_LEASE_EXPIRED | 503 | Too little of the candidate's write window was left to store it safely, so nothing was stored. | Retry. |
DOCUMENT_SET_TOO_LARGE | 400 | More documents than one compile carries were sent to the single-compile route. | Use POST /compile-jobs, which partitions a larger selection into parts server-side. |
CORPUS_TOO_LARGE | 400 | More documents than one run carries. | Split the selection across runs. |
SPLIT_PART_LIMIT_EXCEEDED | varies | Partitioning the selection would make more parts than a run holds. | Split the selection across runs. |
COMPILE_JOB_NOT_FOUND | 404 | No such job in this workspace. Job ids are workspace-scoped, so this is also the answer for another tenant's id. | List GET /compile-jobs to recover the id. |
COMPILE_JOB_SCOPE_INVALID | varies | The job exists and belongs to another workspace. | Use a job from your own workspace. |
COMPILE_JOB_ALREADY_SETTLED | 409 | The job had already finished. Nothing was discarded — a cancel arriving a second after a compile finished does not destroy the result. | Read the job: it is terminal, and its result stands. |
COMPILE_JOB_SLOT_CONFLICT | 409 | A part of this corpus is already held by a job over a different document set. Retrying does not clear it. | Let the holding job settle, or cancel it, before resubmitting. |
OCR_NOT_READY | 409 | The sources have not finished being read. | Retry rather than fail. Poll the job's events until reading completes. |
COMPILE_INPUT_TOO_LARGE | 413 | The selected documents' readings are more than one compile request can carry. Refused before the compile runtime was called; nothing was charged. The job's events name the document and the bytes. | Compile fewer documents at a time. |
SECURITY_BLOCKER_REQUIRES_EXPLICIT_REMOVAL | 409 | continue was sent while a source was held by a safety check. | Use remove_blocked, which records who removed it. continue will not step over a security blocker, because a pipeline that learns to skip security stops has stopped being one. |
CORE_NOT_CONFIGURED | 503 | The compile runtime is unavailable. The request was not charged. | Retry. /api/status reports the deployment's state. |
CORE_UNAVAILABLE | 503 | The compile runtime was reachable and did not answer. | Retry. Nothing was charged. |
CORE_OUTPUT_TOO_LARGE | 422 | The compile output is larger than a stored World can be. Either the runtime refused it against its own budget, or its answer exceeded the read bound; in both cases nothing was signed, audited or stored. The job's events carry the bytes, the bound and, when the runtime reported them, its region, claim, contradiction-pair and file counts. | Retrying gives the same answer. Report it with the job id. |
CORE_REQUEST_INVALID | varies | The compile runtime refused the request it was handed. | Nothing a caller can send. Report it with the job id. |
CORE_RECEIPT_INVALID | varies | The compile runtime answered with a receipt that did not validate, so the result was refused rather than stored. | Retry. Fail-closed by design: a result that cannot be validated is not a smaller result. |
COMPILE_JOB_STORE_NOT_CONFIGURED | 503 | The durable job store is not configured. | Nothing a caller can send. |
COMPILE_JOB_STORE_READ_FAILED | 503 | The durable job store could not be read. | Retry. |
COMPILE_JOB_STORE_WRITE_FAILED | 503 | The durable job store could not be written, so the intent was not recorded. | Retry. Submitting the same set again converges on one job. |
COMPILE_JOB_RPC_UNDEFINED | 503 | The job store is missing a procedure this build expects — a deployment mismatch. | Nothing a caller can send. Report it. |
Worlds, retrieval and answers
Reading a World, and what Search and Ask refuse rather than weaken.
| Code | Status | Meaning | What to do |
|---|---|---|---|
ACTIVE_WORLD_NOT_FOUND | 409 | Nothing has been activated for this collection, so there is no World to read, index or answer from. A candidate nobody accepted is not a smaller answer — it is a different one. | Promote a candidate in a signed-in session. No key can promote. |
ACTIVE_WORLD_CONFLICT | 409 | Two activations raced; neither was applied silently. | Re-read the World and retry the activation. |
WORLD_TRANSITION_IDEMPOTENCY_CONFLICT | 409 | The transition idempotency key was already bound to a different activation or rollback request. | Reuse the key only for the identical request, or generate a fresh key after re-reading the active World. |
WORLD_VERSION_BINDING_CONFLICT | 409 | The requested transition was bound to a World revision that is no longer current. | Re-read the active World and submit the transition against its current revision. |
WORLD_SOURCE_REVISION_SUPERSEDED | 409 | A connector source in this candidate has a newer bound revision than the one the candidate was compiled from, so promoting it would publish replaced content. Checked under lock in the same transaction as the activation. | Compile again from the current sources and promote that candidate. |
WORLD_SOURCE_REVISION_AMBIGUOUS | 409 | A connector source in this candidate has no single latest revision (an unresolved legacy equal-instant tie), so currency cannot be established. | Let the next sync record the provider's current revision, then compile and promote again. |
WORLD_TRANSITION_FORBIDDEN | 403 | The transition was refused because the current principal may no longer change this World. | Refresh your session and workspace membership; an owner or admin must perform the transition. |
ACTIVE_WORLD_CHANGED_RETRY | 409 | The active version changed while the request was in flight. | Retry. The answer would have mixed two versions. |
CONSUMER_CONTEXT_SNAPSHOT_MISMATCH | 409 | A consumer context is bound and the World snapshot does not match it: manifest named a digest other than the one the context resolved to, or the World moved between resolving the snapshot and serving it. Refused rather than answered from another World under this context. | Omit manifest, or send the digest the context is bound to. For a latest context, retry; for a pinned one, re-pin to the current snapshot. |
ACTIVE_WORLD_ARTIFACT_INVALID | 422 | The activated artifact failed validation on read, so it was refused rather than served partially. | Recompile. Report it with the manifest digest. |
ACTIVE_WORLD_BINDING_INVALID | varies | The active pointer names a version the store cannot resolve. | Report it with the collection id. |
ACTIVE_WORLD_RETRIEVAL_INVALID | varies | The active World's retrieval state did not validate. | Rebuild the index with POST /collections/{id}/retrieval-index. |
ACTIVE_WORLD_STORE_UNAVAILABLE | 503 | The World store could not be reached. | Retry. |
WORLD_NOT_FOUND | 404 | No World for that collection id in this workspace. | Check the id, and that it belongs to your workspace. |
WORLD_LENS_NOT_FOUND | 404 | The lens name is not one of objects, relations, evidence, history, files, review. | Use one of the six. |
WORLD_READ_MODEL_INVALID | 422 | The read model failed validation, so nothing was served. | Report it with the manifest digest. |
WORLD_STORE_NOT_CONFIGURED | 503 | The World store is not configured. | Nothing a caller can send. |
WORLD_STORE_READ_FAILED | 503 | The World store could not be read. | Retry. |
WORLD_STORE_WRITE_FAILED | 503 | The World store could not be written. | Retry. |
WORLD_VERSION_BINDING_INVALID | varies | A retained version could not be bound to its manifest. | Report it with the collection id. |
WORLD_CANDIDATE_NOT_PROMOTABLE | 422 | The candidate failed the checks activation requires. | Read the validation report in the candidate; it names what failed. |
WORLD_CANDIDATE_EVIDENCE_REQUIRED | 422 | The candidate has no readable source-bound evidence, so publication or restoration was refused. | Recompile from source regions and inspect the evidence before publishing. |
ROLLBACK_TARGET_ARTIFACT_INVALID | 422 | The retained rollback artifact does not match its collection, manifest or qualified runtime. | Choose a valid retained version from World history; report a damaged artifact. |
WORLD_CANDIDATE_SOURCE_BINDING_INVALID | 422 | A candidate object cites a source version the store cannot resolve. | Recompile. A World with an unresolved link is not emitted. |
WORLD_EQUIVALENCE_REFUSED | 409 | The activation would have replaced the active World with one the equivalence check does not accept as the same subject. | Review the diff before promoting. |
EVIDENCE_DANGLING | varies | An object cites evidence that is not in the package. | Recompile. Fail-closed: the World is not emitted rather than emitted incomplete. |
ROLLBACK_TARGET_NOT_FOUND | 404 | The version to roll back to is not retained. | Read the history lens for the versions that are. |
ROLLBACK_TARGET_CONFLICT | 409 | The rollback target no longer matches the retained history or active revision used to authorize the request. | Re-read the World history and choose a target from the current response. |
PROMOTION_ROLE_REQUIRED | 403 | Activation needs the workspace owner or admin role. | Ask an owner or admin to activate. |
ROLLBACK_ROLE_REQUIRED | 403 | Rollback needs the workspace owner or admin role. | Ask an owner or admin to roll back. |
RETRIEVAL_COMPILE_ROLE_REQUIRED | 403 | Rebuilding the retrieval index needs the workspace owner or admin role, on top of the scope. | Ask an owner or admin to rebuild. |
RETRIEVAL_RUN_NOT_FOUND | 409 | The active World has no completed retrieval compile run, so there is no queryable index. Search has no fallback — a weaker answer presented as the real one is worse than a refusal you can act on. | POST /collections/{id}/retrieval-index rebuilds it. The body carries retrievalIndex and retrievalNotice saying which state it is in. |
RETRIEVAL_PROFILE_NOT_FOUND | 409 | The retrieval profile the index was compiled against is not registered. | Rebuild the index. |
RETRIEVAL_INDEX_NOT_COMPILED | 503 | A rebuild did not reach a queryable index. retrievalIndex.errorClass names the failure class. Never answered as a 200. | Read errorClass, then retry. An embedder outage and an empty corpus are different problems. |
RETRIEVAL_RUNTIME_UNAVAILABLE | 503 | The exact retrieval runtime bound to this compiled index is unavailable or failed its identity checks, so the request was refused instead of silently using a different model. | Retry after the configured runtime is restored, or rebuild the index against an available registered profile. |
RETRIEVAL_COMPILE_NO_UNITS | varies | The World produced no retrievable units, so there was nothing to index. | Check the compile: a World with no evidence has nothing to retrieve. |
RETRIEVAL_COMPILE_EMBEDDING_PROVIDER_FAILED | varies | The embedding provider failed during the rebuild. | Retry. Dense retrieval is skipped rather than faked when no embedder is configured — see degradations. |
RETRIEVAL_COMPILE_EMBEDDING_WRITE_FAILED | varies | Embeddings could not be written. | Retry. |
RETRIEVAL_COMPILE_UNIT_WRITE_FAILED | varies | Retrieval units could not be written. | Retry. |
RETRIEVAL_COMPILE_PROFILE_REGISTRATION_FAILED | varies | The retrieval profile could not be registered. | Retry. |
RETRIEVAL_COMPILE_RUN_REJECTED | varies | The rebuild run was refused before it started. | Check the active World exists and the plan bar is met. |
RETRIEVAL_COMPILE_SOURCE_BINDING_UNRESOLVED | varies | A retrieval unit cited a source version that could not be resolved, so the index was refused rather than compiled with a dangling citation. | Recompile the World. |
Review and evidence
The append-only decision record, and what it revalidates before it writes.
| Code | Status | Meaning | What to do |
|---|---|---|---|
REVIEW_REQUEST_INVALID | 400 | The review body did not validate. | Check the schema: collectionId, manifestDigest, evidenceId, action and an 8–1000 character reason are all required. |
REVIEW_REQUEST_TOO_LARGE | 413 | The review body exceeded its bound. | Shorten the reason. |
REVIEW_EVIDENCE_NOT_FOUND | 404 | The evidence id is not in the World version named by the digest. | Read the evidence lens for that manifest digest and use an id from it. |
REVIEW_WORLD_CHANGED | 409 | The World changed between reading the evidence and recording the decision, so the decision was not written against a version it may not describe. | Re-read the evidence at the current digest and decide again. |
REVIEW_PATCH_INVALID | 400 | An Edit decision carried a patch that did not validate. | Check the patch shape against the evidence you read. |
REVIEW_RECEIPT_INVALID | varies | The decision receipt did not validate, so nothing was recorded. | Retry. Nothing partial was written. |
REVIEW_STORE_NOT_CONFIGURED | 503 | The review store is not configured. | Nothing a caller can send. |
REVIEW_STORE_READ_FAILED | 503 | The review store could not be read. | Retry. |
REVIEW_STORE_WRITE_FAILED | 503 | The review store could not be written. | Retry. The record is append-only, so a retry does not overwrite. |
PATCH_BEFORE_MISMATCH | 409 | The patch's before value does not match what is stored now. | Re-read the target and rebuild the patch. |
PATCH_TARGET_NOT_FOUND | 404 | The patch names a target the World does not contain. | Re-read the World. |
PATCH_TARGET_NOT_EDITABLE | 409 | The target is not one a review decision may edit. | Accept or Reject instead. |
PATCH_NO_CHANGE | 400 | The patch would change nothing. | Send a patch that differs, or record Accept. |
PATCH_LABEL_INVALID | 400 | The patch label did not validate. | Check the label bounds. |
PATCH_ARTIFACT_INVALID | 422 | Applying the patch would produce an artifact that does not validate. | Fail-closed by design. Narrow the edit. |
REJECT_RECEIPT_INVALID | varies | A Reject decision's receipt did not validate. | Retry. |
Exports and packages
Signed, or refused. There is no third outcome.
| Code | Status | Meaning | What to do |
|---|---|---|---|
EXPORT_SIGNER_NOT_CONFIGURED | 503 | No signing key is configured, so neither a signed archive nor a fingerprint can be produced. GET /export/trust answers this rather than a fingerprint nobody can verify against. | Nothing a caller can send. A deployment without a signer cannot hand out an archive at all — that is the contract, not an outage. |
EXPORT_SIGNER_INVALID | 503 | The configured signer did not produce a usable key. | Nothing a caller can send. Report it. |
SIGNATURE_READ_FAILED | 503 | The detached signature could not be read. | Retry the download. |
INVALID_SIGNATURE | 422 | The signature did not verify against the key it names. | Do not trust the archive. Re-download, and verify against the fingerprint from GET /export/trust rather than one inside the archive. |
COLLECTION_PACKAGE_INVALID | 422 | The package failed its own validation, so it was not served. | Recompile. A package whose file digests do not match is not served. |
COLLECTION_PACKAGE_TOO_LARGE | 422 | The stored World's package is larger than one read may load, so it was not opened, downloaded, answered from or activated. The body carries bytes (the package's stored content) and bound. Nothing in the stored World was changed. | Retrying gives the same answer. Compile the same sources in smaller groups. |
COLLECTION_KEY_INVALID | 400 | The package object key did not validate. | Report it with the collection id. |
COLLECTION_SOURCE_BINDING_INVALID | 422 | A package entry cites a source version that cannot be resolved. | Recompile. |
COLLECTION_JSON_PREFIX_REQUIRED | varies | The package store is configured with a prefix the request did not use. | Nothing a caller can send. Report it. |
R2_NOT_CONFIGURED | 503 | Object storage is not configured. | Nothing a caller can send. |
DELETION_NOT_PROVEN | varies | A delete was requested and the store could not prove it happened, so success was not reported. | Retry. Fail-closed: an unproven delete is not reported as a delete. |
RESTORE_NOT_PROVEN | varies | A restore could not be proven. | Retry. |
Connections and connectors
Durable cursors, and the refusals that keep two syncs from disagreeing.
| Code | Status | Meaning | What to do |
|---|---|---|---|
GOOGLE_VIEWER_LINK_NOT_ENABLED | 503 | Google Drive identity linking is not enabled. | Use an enabled connector or retry after this integration is configured. |
GOOGLE_VIEWER_LINK_CONSENT_INVALID | varies | The Google consent response did not prove the requested viewer-only access and consent state. | Restart authorization and grant the requested viewer-only permission. |
OAUTH_REFRESH_TOKEN_MISSING | varies | The OAuth provider returned no refresh token for a connector that requires persistent access. | Re-authorize the connector with the provider's offline access consent enabled. |
CONNECTION_NOT_FOUND | 404 | No such connection in this workspace. | List GET /connections. |
CONNECTION_NOT_SYNCABLE | 409 | The connection is revoked or in a state that does not accept a batch. | Re-create the connection. |
CONNECTION_CREATE_FAILED | 503 | The connection could not be recorded. | Retry. |
CONNECTION_REVOKE_FAILED | 503 | The revoke could not be recorded, so it is not reported as done. Immutable outputs are retained by design when a revoke does succeed. | Retry. A revoke that cannot be proven is not reported as a revoke. |
CONNECTION_BATCH_CONFLICT | 409 | The batch's previousCursorSha256 does not match the committed cursor — another sync moved it. | Re-read the connection's cursor and rebuild the batch from it. |
CONNECTION_CURSOR_CONFLICT | 409 | Two batches tried to advance the same cursor. | Re-read the cursor and retry. Replaying the identical batch is idempotent. |
CONNECTION_BATCH_FAILED | 503 | The batch could not be applied. | Retry with the same batchId: an identical replay is idempotent, not a second apply. |
INVENTORY_CONTRACT_INVALID | 400 | An inventory scan step did not match its schema: unknown field, bad scan id, counts that cannot be paged, or an epoch that does not exceed the expected head. | Check the ConnectionInventoryRequest schema. |
INVENTORY_ITEM_INVALID | 400 | An inventory item failed validation (id or revision bounds, digest, size or MIME type). | Check the ConnectionInventoryItem schema bounds. |
INVENTORY_PAGE_INDEX_INVALID | 400 | The page index is outside the scan's declared page count. | Send pages 0 to pageCount - 1. |
INVENTORY_NOT_ATTESTED_COMPLETE | 400 | finalize was sent without complete: true. An incomplete scan never marks anything missing. | Finalize only after the whole source was read; otherwise abandon the scan. |
INVENTORY_ACTOR_INVALID | 403 | The key or user no longer holds this workspace with connections:sync. | Use an active key with the connections:sync scope. |
INVENTORY_HEAD_STALE | 409 | expectedHeadEpoch is not the connection's current inventory head; another scan finalized first. The response carries headEpoch. | Begin a new scan naming the returned headEpoch. |
INVENTORY_EPOCH_STALE | 409 | An open scan with an equal or newer epoch exists; an older scan cannot replace it. | Use a larger scanEpoch, or let the newer scan finish. |
INVENTORY_SCAN_CONFLICT | 409 | The scan id was already begun with different parameters. | Use a new scan id. |
INVENTORY_SCAN_NOT_FOUND | 409 | No such scan on this connection in this workspace. | Begin a scan first. |
INVENTORY_SCAN_NOT_OPEN | 409 | The scan was finalized or superseded by a newer one and accepts no more steps. | Begin a new scan. |
INVENTORY_SCAN_EXPIRED | 409 | The scan stayed open past its six-hour limit and was abandoned. | Begin a new scan. |
INVENTORY_PAGE_CONFLICT | 409 | A page with this index was already staged with different items. An identical page is a replay, not a conflict. | Begin a new scan; a scan's pages are immutable. |
INVENTORY_COUNT_MISMATCH | 409 | The staged or restated item/page counts disagree with the counts declared at begin. | Begin a new scan with the correct counts. |
INVENTORY_PAGES_INCOMPLETE | 409 | finalize was sent before every declared page was staged. | Stage the missing pages, then finalize. |
INVENTORY_DUPLICATE_ITEM | 409 | The same nativeId appears more than once in the scan. | Deduplicate the inventory and begin a new scan. |
INVENTORY_FINALIZE_CONFLICT | 409 | The scan was already finalized with different counts. | Read the stored receipt with an identical finalize, or begin a new scan. |
INVENTORY_LIMIT_EXCEEDED | 413 | The scan's staged pages passed the 64 MiB per-scan bound. | Split the source into smaller registered scopes. |
INVENTORY_UNAVAILABLE | 503 | The inventory step could not be recorded or classified, so it is not reported as done. | Retry the identical step: begin, page and finalize replays are idempotent. |
SOURCE_CURSOR_STALE | 409 | The cursor the batch carries is behind the committed one. | Re-read the cursor and collect from there. |
SOURCE_CURSOR_TOO_LARGE | 413 | The cursor value exceeded its bound. | Report it with the connection id. |
SOURCE_DIGEST_REQUIRED | 400 | An event carried bytes with no contentSha256. | Compute the digest at the source. An event without one cannot be bound to a document. |
SOURCE_DIGEST_MISMATCH | 409 | The bytes do not hash to the digest the event declared. | Re-read the file and recompute the digest. |
SOURCE_DIGEST_CONFLICT | 409 | Two events declare different digests for the same revision. | Re-collect the revision. |
SOURCE_IDENTITY_INVALID | 400 | The event's nativeId/revision pair did not validate. | Check the ConnectionEvent schema bounds. |
SOURCE_REVISION_MISMATCH | 409 | The revision the event names is not the one recorded. | Re-read the cursor and collect again. |
SOURCE_VERSION_CHANGED | 409 | The source version changed under the batch. | Retry from the committed cursor. |
SOURCE_VERSION_DIGEST_CONFLICT | 409 | A version is already recorded with a different digest. | Re-collect the version. |
SOURCE_METADATA_INVALID | 400 | Event metadata did not validate. | Check the ConnectionEvent schema. |
SOURCE_LIFECYCLE_REVIEW_REQUIRED | 409 | A lifecycle transition on this source needs a person. | Nothing automatic clears it. |
SOURCE_DOWNLOAD_FAILED | 503 | The agent could not read the source's bytes. | Check the agent's credentials and the source's availability. |
CONNECTOR_SOURCE_ACCESS_DENIED | 401 | The provider refused the stored credential. | Re-authorize the connector. |
CONNECTOR_SOURCE_ACCESS_UNAVAILABLE | 503 | The provider could not be reached. | Retry. |
CONNECTOR_SOURCE_SUSPENSION_UNRESOLVED | 409 | The connector is suspended and the suspension has not been cleared. | Re-authorize, or revoke and re-create the connection. |
CONNECTOR_BINDING_INVALID | varies | The connector binding did not validate. | Re-create the connection. |
CONNECTOR_BINDING_CONFLICT | 409 | Two bindings claim the same connector. | Revoke one. |
OAUTH_PROVIDER_NOT_CONFIGURED | 503 | The provider's client is not configured. Fails closed rather than starting an authorization that cannot complete. | Check /integrations for which providers are live here. |
OAUTH_SECRET_BROKER_NOT_CONFIGURED | 503 | The managed secret broker is not configured, so no refresh secret could be stored — or, on a revoke, deleted. | Nothing a caller can send. |
OAUTH_AUTHORIZATION_START_FAILED | 503 | The single-use PKCE authorization could not be created. | Retry. |
OAUTH_AUTHORIZATION_INVALID | 400 | The authorization is expired, already used, or does not match this workspace. Authorizations are single-use by design. | Start a new authorization. |
OAUTH_PROVIDER_DENIED | 403 | The user declined at the provider. | Start the authorization again. |
OAUTH_PROVIDER_INVALID | varies | The callback path named a provider TAVONEL does not have a connector for. Carried back on the workspace redirect rather than as a JSON body. | Start the authorization from POST /oauth-connectors/authorize; do not construct the callback URL yourself. |
OAUTH_CALLBACK_INVALID | 400 | The callback did not carry a state TAVONEL issued. | Start the authorization again; do not construct the callback yourself. |
OAUTH_CALLBACK_FAILED | 503 | The callback could not be completed. | Start the authorization again. |
OAUTH_CONNECTION_NOT_FOUND | 404 | No such OAuth connection in this workspace. | List GET /oauth-connectors. |
OAUTH_SECRET_REVOCATION_FAILED | 503 | The refresh secret could not be deleted, so the revoke was not reported as done. | Retry. A revoke is reported only when the secret is gone. |
OAUTH_TOKEN_REFRESH_FAILED | 503 | The provider refused the refresh token. | Re-authorize the connector. |
OAUTH_SOURCE_TARGET_UNSUPPORTED | 400 | The requested source target is not one this connector reads. | Check /integrations for what each provider covers here. |
OAUTH_STORE_NOT_CONFIGURED | 503 | The OAuth store is not configured. | Nothing a caller can send. |
OAUTH_STORE_UNAVAILABLE | 503 | The OAuth store could not be reached. | Retry. |
JOB_NOT_FOUND | 404 | No such run in this workspace. | Use a run id from the response that started it. |
JOB_SCOPE_INVALID | 404 | The run exists and belongs to another workspace. Answered as not found rather than as forbidden, so an id cannot be probed across tenants. | Use a run from your own workspace. |
JOB_SYNC_CONFLICT | 409 | Two syncs raced on the same run. | Retry. |
JOB_CONNECTION_MISSING | 409 | The run names a connection that no longer exists. | Re-create the connection. |
JOB_CONNECTION_UNAVAILABLE | 503 | The run's connection could not be read. | Retry. |
JOB_CURSOR_INVALID | 400 | The run's cursor did not validate. | Restart the sync from the committed cursor. |
JOB_STORE_READ_FAILED | 503 | The run store could not be read. | Retry. |
JOB_STORE_WRITE_FAILED | 503 | The run store could not be written. | Retry. |
Keys and audit
Management routes, which no API key can call — they take a signed-in browser session.
| Code | Status | Meaning | What to do |
|---|---|---|---|
API_KEY_NOT_FOUND | 404 | No such key in this workspace. | List the keys in Workspace → Developers. |
API_KEY_CREATE_FAILED | 503 | The replacement key could not be written, so nothing was revoked either. | Retry. Rotation is atomic: either both happened or neither did. |
API_KEY_ROTATE_FAILED | 503 | The rotation could not be completed. | Retry, then check which keys exist before assuming either outcome. |
API_KEY_REVOKE_FAILED | 503 | The revoke could not be recorded. | Retry. A revoke is reported only when it is written. |
DEVELOPER_STORE_NOT_CONFIGURED | 503 | The developer store is not configured. | Nothing a caller can send. |
DEVELOPER_STORE_READ_FAILED | 503 | The developer store could not be read. | Retry. |
DEVELOPER_STORE_BINDING_INVALID | 503 | A stored row did not validate, so it was refused rather than returned partially. | Report it. |
DEVELOPER_AUDIT_READ_FAILED | 503 | The audit trail could not be read. | Retry. |
DEVELOPER_AUDIT_WRITE_FAILED | 503 | An audit event could not be written, so the action it describes was refused. Every key create, rotate and revoke writes an audit row or does not happen. | Retry. |
Source export and deletion
/api/documents/{id}/lifecycle: what a workspace manager is told when exporting or deleting an uploaded source.
| Code | Status | Meaning | What to do |
|---|---|---|---|
CUSTOMER_SOURCE_DELETE_SESSION_REQUIRED | 403 | Deleting a source needs a signed-in person; an API key cannot delete. | Sign in as a workspace owner or admin and retry from the workspace. |
WORKSPACE_MANAGER_REQUIRED | 403 | Only a workspace owner or admin can plan or request a deletion. | Ask an owner or admin of this workspace. |
DELETION_MODE_INVALID | 400 | mode was neither dry_run nor execute. | Send dry_run first, then execute with the plan's digest. |
CUSTOMER_SOURCE_NOT_AN_UPLOAD | 400 | The id is not an uploaded source, so this route cannot delete it. Connected sources are deleted at their origin. | Delete the file in the connected provider. |
CONFIRM_MANIFEST_REQUIRED | 400 | execute must echo the manifestSha256 of the dry-run plan. | Run dry_run, then send its manifestSha256 as confirmManifestSha256. |
CUSTOMER_SOURCE_MANIFEST_CHANGED | 409 | The stored objects changed since the plan you confirmed, so nothing was deleted. The body carries the new plan. | Review the new plan and confirm its digest. |
CUSTOMER_SOURCE_DELETE_FORBIDDEN | 403 | The database re-checked membership and the caller is not an active owner or admin of this workspace. | Ask an owner or admin of this workspace. |
CUSTOMER_SOURCE_CONNECTOR_BOUND | 409 | The document came from a connected provider; deleting it here would be undone by the next sync. | Delete the file in the provider. |
SOURCE_LEGAL_HOLD_ACTIVE | 409 | A legal hold covers this workspace, so no source in it can be deleted. | The hold has to be released first; contact your administrator or TAVONEL. |
SOURCE_LEGAL_HOLD_STATE_UNKNOWN | 409 | The workspace's legal-hold state could not be read, so deletion is refused rather than assumed safe. | Contact TAVONEL; this is a configuration problem, not something a retry fixes. |
CUSTOMER_SOURCE_DELETE_STORE_FAILED | 503 | The deletion ledger could not be read or written. Nothing was recorded. | Retry; a retry of a recorded request replays the same receipt. |
Generic
Codes that are deliberately vague, and what that vagueness means.
| Code | Status | Meaning | What to do |
|---|---|---|---|
NOT_FOUND | varies | The addressed resource does not exist in this workspace. Deliberately uniform across tenants: the same answer for an id that is not yours and an id that is nobody's. | Check the id, and that it belongs to the workspace the key names. |
READ_FAILED | 503 | A backing store could not be read. | Retry. |
DELETE_FAILED | 503 | A delete could not be completed. | Retry. |
IDEMPOTENCY_KEY_INVALID | 400 | The idempotency key did not match the expected shape. | Send a sha256 hex digest, or omit the header. |
IDEMPOTENCY_CONFLICT | 409 | The same idempotency key was used for a different request body. | Use a fresh key, or re-send the original body. |
IDEMPOTENCY_IN_PROGRESS | 409 | A request with this key is still running. | Poll rather than resubmit. |
COMPUTE_IDEMPOTENCY_CONFLICT | 409 | The processing reservation ledger already holds a different reservation under this request's idempotency key. | Use a fresh source idempotency key, or re-send the original request unchanged. Nothing was charged twice. |
CONTENT_LENGTH_INVALID | 400 | content-length was absent or unparseable where the route requires it. | Send an accurate content-length. |
CONTENT_LENGTH_MISMATCH | 400 | The body length did not match the declared content-length. | Send an accurate content-length. |
Two numbers a client branches on
Note Two numbers this page used to state in prose, for anyone who arrived looking for them: a run carries at most 128 documents and one compile at most 12, and the hourly allowance on World activations, rollbacks and retrieval-index rebuilds is 20 of each. Both are imported from the modules that enforce them, so the page cannot quote a limit the code does not hold.
API version 2026-09-02.1 · reviewed 11 September 2026
Something here out of date or wrong? Report an issue with this page.