Native API problem codes
Jiandu request failures normally use RFC 9457 application/problem+json. Branch on the stable
code, not title: the title is human-facing and may be localized. Retain the
requestId for operator correlation and accept unknown future codes without losing the HTTP status.
{
"type": "https://jiandu.org/docs/references/problem-codes?code=documents.stale-revision",
"title": "The document changed after you opened it.",
"status": 412,
"instance": "urn:uuid:0f2c9d24-6a6b-4f8b-9f5b-1a2c3d4e5f60",
"code": "documents.stale_revision",
"requestId": "0f2c9d24-6a6b-4f8b-9f5b-1a2c3d4e5f60",
"retry": "do_not_retry"
}
Each type URI dereferences to this public catalog with its rendered code in the query string. Dots
stay dots and underscores become hyphens in type; code remains the exact machine value to search
on this page. do_not_retry means do not repeat the unchanged request. retry_with_backoff means use
bounded exponential backoff with jitter and honor Retry-After when present. For idempotent intake,
reuse the same key only with identical semantic input.
:::caution Current contract boundary This field guide records problem codes reachable in the current source by API family. The generated OpenAPI operation pages describe response envelopes and common statuses, but do not yet associate every code with every operation. Transport middleware, timeouts, method mismatches, and asynchronous task or batch-item failures may use other response shapes. Generate clients from the contract shipped with the running Jiandu version and retain a safe unknown-error branch. :::
Shared and system
| Code | HTTP / retry | Meaning and safe action |
|---|---|---|
authentication_required | 401 / do not retry | A credential is absent, ambiguous, expired, revoked, or invalid. Reauthenticate and send exactly one supported credential. |
permission_denied | 403 / do not retry | The principal lacks the required permission. Use an authorized member or adjust RBAC. |
personal_access_scope_insufficient | 403 / do not retry | The PAT lacks the required scope, or this credential-management route rejects PATs. Issue an appropriate PAT or use an ordinary session. |
not_found | 404 / do not retry | The resource is absent or intentionally hidden by household or document scope. Verify the scoped identifier and access. |
origin_forbidden | 403 / do not retry | A mutation failed same-origin checks. Correct Origin and Fetch Metadata and use the configured Jiandu origin. |
ingress_not_allowed | 421 / do not retry | Host authority or direct peer is outside the ingress boundary. Correct proxy, public-origin, Host, or trusted-peer configuration. |
auth_unavailable | 503 / backoff | An authentication dependency failed. Check health and retry later. |
clock_unavailable | 503 / backoff | System time could not be represented safely. Repair the host clock or time configuration. |
database_unavailable | 503 / backoff | Database readiness failed. Check the configured database and its TLS path. |
blob_storage_unavailable | 503 / backoff | Blob-storage readiness failed. Check the configured backend. |
integrity_check_in_progress | 429 / backoff | Another bounded integrity check owns the slot. Honor Retry-After. |
integrity_check_unavailable | 503 / backoff | The integrity diagnostic failed operationally. Check health and logs. |
invalid_frontend_diagnostics | 400 or 413 / do not retry | The diagnostic batch violates its closed schema or request-size bound. Correct and bound the body. |
frontend_diagnostics_busy | 429 / backoff | Diagnostic capacity is occupied. Retry later. |
Sessions, setup, and membership
| Code | HTTP / retry | Meaning and safe action |
|---|---|---|
invalid_session_request | 400 or 413 / do not retry | Session JSON is malformed or oversized. Correct and bound the body. |
account_conflict | 409 / do not retry | A username or account identifier already exists. Choose another or use the existing account. |
owner_recovery_required | 403 / do not retry | Only the installation Owner may perform the requested credential recovery. |
installation_setup_already_claimed | 409 / do not retry | Setup was already claimed. Continue through normal administration. |
installation_setup_claim_not_allowed | 403 / do not retry | Use an eligible ordinary browser session to claim setup. |
invalid_installation_setup_claim | 400 or 413 / do not retry | Setup-claim JSON or token shape is invalid or oversized. |
installation_setup_token_invalid | 401 / do not retry | The setup token was not accepted. Obtain the current protected token. |
invalid_local_account_request | 400 or 413 / do not retry | Username, password, display name, role, or body size is invalid. |
invalid_personal_access_token_request | 400 or 413 / do not retry | PAT label, scopes, expiry, or body size is invalid. |
invalid_membership_invitation_request | 400, 413, 415, or 422 / do not retry | Invitation JSON, content type, lifetime, role, or restrictions are invalid. |
membership_invitation_role_not_found | 422 / do not retry | The requested role does not exist. Select a current role. |
membership_invitation_capacity_exceeded | 422 / do not retry | The household invitation limit is reached. Revoke or consume invitations first. |
membership_invitation_not_found | 404 / do not retry | The invitation is absent or outside scope. |
membership_invitation_consumed | 409 / do not retry | A consumed invitation cannot be revoked. |
membership_invitation_unavailable | 503 / backoff | Invitation persistence, entropy, or clock dependency failed. |
Authorization administration
| Code | HTTP / retry | Meaning and safe action |
|---|---|---|
invalid_authorization_request | 400, 413, 415, or 422 / do not retry | JSON, content type, identifiers, permissions, or another bounded field is invalid. |
authorization_role_not_found | 404 / do not retry | The role does not exist in this household. |
authorization_group_not_found | 404 / do not retry | The group does not exist in this household. |
authorization_member_not_found | 404 / do not retry | The member does not exist in this household. |
authorization_capacity_exceeded | 422 / do not retry | A role, group, or membership limit is reached. Remove unused objects first. |
owner_membership_protected | 403 / do not retry | Owner membership state is immutable through this endpoint. |
owner_role_protected | 403 / do not retry | The built-in Owner role cannot be removed from the Owner. |
authorization_unavailable | 503 / backoff | Authorization state is temporarily unavailable. |
OIDC, LDAP, trusted proxy, and linked identities
| Code | HTTP / retry | Meaning and safe action |
|---|---|---|
invalid_oidc_request | 400 or 413 / do not retry | OIDC start or link input is malformed or oversized. |
oidc_disabled | 404 / do not retry | The provider is not enabled. Use another method or update operator configuration. |
oidc_invalid_callback | 400 / do not retry | The callback is invalid or expired. Restart sign-in rather than replaying it. |
oidc_start_limited | 429 / backoff | OIDC-start capacity is occupied. Retry with bounded backoff. |
oidc_admission_denied | 403 / do not retry | The identity is not admitted. Correct the invitation or provider admission policy. |
oidc_identity_conflict | 409 / do not retry | The identity or provider is already linked. Reconcile the existing link. |
oidc_unavailable | 503 / backoff | The OIDC or provider dependency failed. |
invalid_ldap_request | 400 or 413 / do not retry | LDAP credential or link JSON is malformed or oversized. |
ldap_disabled | 404 / do not retry | The LDAP provider is disabled. |
ldap_invalid_credential | 401 / do not retry | Directory credentials were not accepted. Reauthenticate. |
ldap_admission_denied | 403 / do not retry | The directory identity is not admitted. Correct the configured policy. |
ldap_identity_conflict | 409 / do not retry | The directory identity or provider is already linked. |
ldap_unavailable | 503 / backoff | Directory authentication is unavailable or misconfigured. Inspect configuration before repeated retries. |
invalid_trusted_proxy_request | 400 or 413 / do not retry | Trusted-proxy request input is malformed or oversized. |
trusted_proxy_disabled | 404 / do not retry | The trusted-proxy provider is disabled. |
trusted_proxy_invalid_assertion | 401 / do not retry | The proxy assertion or protected header is invalid. Correct the trusted proxy chain. |
trusted_proxy_admission_denied | 403 / do not retry | The asserted identity is not admitted. |
trusted_proxy_identity_conflict | 409 / do not retry | The proxy identity or provider is already linked. |
trusted_proxy_unavailable | 503 / backoff | A trusted-proxy authentication dependency failed. |
recent_sign_in_required | 409 / do not retry | Reauthenticate interactively before changing a linked identity. |
identity_invalid_credential | 401 / do not retry | The linked-identity operation requires a valid ordinary session. |
identity_admission_denied | 403 / do not retry | The external identity is not admitted. |
identity_account_conflict | 409 / do not retry | The identity or provider is already linked. |
identity_not_found | 404 / do not retry | The requested identity link does not exist. |
identity_last_credential | 409 / do not retry | Add another interactive sign-in method before unlinking this one. |
identity_unavailable | 503 / backoff | External identity management is unavailable. |
Passkeys
The current contract contains two legacy naming forms. Treat each literal code as distinct until a future compatibility migration publishes aliases.
| Code | HTTP / retry | Meaning and safe action |
|---|---|---|
passkey_invalid_request | 400 or 413 / do not retry | Transport-level passkey JSON is malformed or oversized. |
passkey.invalid_request | 400 / do not retry | WebAuthn semantic input is invalid. Restart the ceremony. |
passkeys_disabled | 404 / do not retry | Passkeys are not enabled. |
passkey.invalid_credential | 401 / do not retry | The credential or assertion was not accepted. Restart authentication. |
passkey.recent_sign_in_required | 409 / do not retry | Sign in again before changing passkeys. |
passkey.account_conflict | 409 / do not retry | The account identifier or passkey already exists. |
passkey.credential_not_found | 404 / do not retry | The passkey does not exist. |
passkey.last_credential | 409 / do not retry | Add another interactive credential before removal. |
passkey.capacity_exceeded | 429 / backoff | Passkey or ceremony capacity is reached. Back off; if persistent, remove an unused passkey. |
passkey.admission_denied | 403 / do not retry | The invitation cannot admit this passkey registration. |
passkey.unavailable | 503 / backoff | The passkey service or persistence layer is unavailable. |
passkey_unavailable | 503 / backoff | The API adapter could not issue or serialize the passkey session. |
Intake and resumable uploads
| Code | HTTP / retry | Meaning and safe action |
|---|---|---|
intake.invalid_multipart | 400 / do not retry | Send exactly one file and one allowDuplicate field. |
intake.invalid_batch_multipart | 400 / do not retry | Send two through one hundred files fields only. |
intake.invalid_idempotency_key | 400 / do not retry | Supply exactly one bounded valid key. |
intake.invalid_request | 422 / do not retry | Intake semantics are invalid. Correct the request. |
intake.invalid_filename | 422 / do not retry | The filename is empty, unsafe, controlled, or too long. |
intake.parse_budget_exceeded | 422 / do not retry | The file exceeded the safe parser budget. Repair or simplify the source. |
intake.request_too_large | 413 / do not retry | The aggregate multipart request exceeds the configured bound. |
intake.size_limit_exceeded | 413 / do not retry | The document exceeds the configured per-file limit. |
intake.unsupported_original | 415 or 422 / do not retry | Declared or terminally inspected content is unsupported. Convert to an advertised input type. |
intake.duplicate | 409 / do not retry | Matching content exists. Use it or explicitly allow a duplicate. |
intake.idempotency_conflict | 409 / do not retry | The key was used with different input. Reuse it only with identical input. |
intake.batch_item_conflict | 409 / do not retry | A batch item already has a different durable result. Read current batch state. |
intake.upload_not_accepted | 409 / do not retry | Transfer ended without document acceptance. Read upload status. |
intake.source_changed | 422 / do not retry | Source bytes or metadata changed during transfer. Restart from a stable source. |
intake.parser_busy | 503 / backoff | The bounded parser is occupied. Retry later. |
intake.finalization_pending | 503 / backoff | The original is durable and still finalizing. Retry with the same key and identical input. |
intake.finalization_failed | 503 / backoff | The durable original could not yet finalize. Retry with the same key. |
storage_unavailable | 503 / backoff | Original storage failed. Check storage health. |
persistence_unavailable | 503 / backoff | Document, task, or batch state is unavailable. |
intake.invalid_resumable_upload | 400 / do not retry | TUS headers, metadata, or length are invalid. |
intake.invalid_upload_content_type | 415 / do not retry | PATCH must use application/offset+octet-stream. |
intake.tus_version_required | 412 / do not retry | Supply Tus-Resumable: 1.0.0. |
intake.upload_not_found | 404 / do not retry | The upload does not exist or is outside the authenticated intake scope. |
intake.upload_state_conflict | 409 / do not retry | The upload is no longer in a compatible state. Read its status. |
intake.upload_offset_conflict | 409 / do not retry | Offset differs from durable state. Use HEAD or GET, then resume there. |
intake.upload_chunk_too_large | 413 / do not retry | Split the transfer into smaller chunks. |
intake.upload_checksum_mismatch | 460 / do not retry | Re-read offset and resend corrected bytes and checksum. |
intake.upload_unavailable | 503 / backoff | The resumable spool or storage dependency is unavailable. |
Documents and explicit access
| Code | HTTP / retry | Meaning and safe action |
|---|---|---|
documents.invalid_query | 400 / do not retry | Correct query parameters. |
documents.invalid_search | 400 / do not retry | Correct search-expression syntax. |
documents.invalid_cursor | 400 / do not retry | The cursor is invalid or mismatched. Restart pagination without it. |
documents.invalid_json | 400 or 413 / do not retry | Mutation JSON is malformed or oversized. |
documents.invalid_request | 422 / do not retry | Document mutation semantics are invalid. |
documents.invalid_idempotency_key | 400 / do not retry | Supply one bounded key for reprocessing. |
documents.precondition_required | 428 / do not retry | Supply the current strong revision in If-Match. |
documents.invalid_precondition | 400 / do not retry | If-Match is not exactly one strong document revision. |
documents.stale_revision | 412 / do not retry | Reload the document and ETag, reconcile, and retry deliberately. |
documents.not_ready | 409 / do not retry | A published result does not exist yet. Poll task or document state. |
documents.invalid_lifecycle_transition | 409 / do not retry | Reload and choose an action valid for the current lifecycle. |
documents.deletion_blocked | 409 / do not retry | Derived references still depend on the document. Remove or wait for them. |
documents.reprocessing_idempotency_conflict | 409 / do not retry | The reprocessing key was used for different input. |
documents.reprocessing_invalid_state | 409 / do not retry | The current lifecycle cannot be reprocessed. |
documents.reprocessing_conflict | 409 / backoff | Incompatible reprocessing is active. Poll and retry later. |
documents.search_not_failed | 409 / do not retry | The search projection is not terminally failed, so retry is inapplicable. |
document_unavailable | 503 / backoff | Document projection, storage, or persistence is unavailable. |
document_access.invalid_query | 400 / do not retry | Correct grant or access query parameters. |
document_access.invalid_json | 400 or 413 / do not retry | Access-policy or grant JSON is malformed or oversized. |
document_access.invalid_request | 422 / do not retry | Access-request semantics are invalid. |
document_access.policy_not_restricted | 409 / do not retry | Set policy to restricted before managing explicit grants. |
document_access_unavailable | 503 / backoff | Access-policy persistence is unavailable. |
Learning and notifications
| Code | HTTP / retry | Meaning and safe action |
|---|---|---|
learning.invalid_json | 400 or 413 / do not retry | Learning-command JSON is malformed or oversized. |
learning.invalid_request | 422 / do not retry | The command is semantically invalid. |
learning.precondition_required | 428 / do not retry | Supply the current aggregate revision. |
learning.invalid_precondition | 400 / do not retry | Supply exactly one strong revision. |
learning.stale_revision | 412 / do not retry | Reload the snapshot and retry against its revision. |
learning.conflict | 409 / do not retry | Suggestion or rule state changed. Reload before choosing an action. |
learning.unavailable | 503 / backoff | Learning state is unavailable. |
notifications.invalid_query | 400 / do not retry | Correct inbox or change-feed filters. |
notifications.invalid_cursor | 400 / do not retry | The cursor is invalid or mismatched. Restart from a valid cursor or full resync. |
notifications.invalid_stream_cursor | 400 / do not retry | Supply at most one bounded SSE cursor. |
notifications.invalid_json | 400 or 413 / do not retry | Notification-command JSON is malformed or oversized. |
notifications.invalid_request | 422 / do not retry | A bulk or item command is invalid. |
notifications.precondition_required | 428 / do not retry | Supply the current preference revision. |
notifications.invalid_precondition | 400 / do not retry | Supply exactly one strong preference revision. |
notifications.stale_preferences | 412 / do not retry | Reload preferences and retry against the current revision. |
notifications.unsupported_channel | 422 / do not retry | Select a channel supported by this deployment profile. |
notifications.stream_capacity_exhausted | 429 / backoff | Use bounded polling and retry SSE later. |
notifications.unavailable | 503 / backoff | Notification persistence is unavailable. |
Email connectors and capture
| Code | HTTP / retry | Meaning and safe action |
|---|---|---|
connectors.invalid | 400 / do not retry | Connector configuration or request input is invalid. |
connectors.not_found | 404 / do not retry | The connector is absent or outside household scope. |
connectors.conflict | 409 / do not retry | Connector revision or authorization state changed. Reload it. |
connectors.oauth_unconfigured | 503 / backoff in current API | OAuth installation configuration is missing. Operator configuration is required; blind retries will not repair it. |
connectors.oauth_unavailable | 503 / backoff | Mailbox authorization could not start. Check provider and configuration. |
connectors.unavailable | 503 / backoff | Connector persistence or provider work failed. |
capture.invalid_request | 400 / do not retry | JSON, identifiers, revision, lease, settings, or upload metadata are invalid. |
capture.invalid_upload_content_type | 415 / do not retry | A capture-agent chunk must use application/offset+octet-stream. |
capture.state_conflict | 409 / do not retry | Connector, job, or lease state changed. Reload or claim a fresh lease. |
capture.canceled | 409 / do not retry | The job was canceled. Stop work; create a new job only if intended. |
capture.agent_credential_invalid | 401 / do not retry | The agent credential is missing, invalid, or revoked. Re-enroll or replace it. |
capture.unavailable | 503 / backoff in current API | Capture is unavailable or not configured. Inspect operator configuration before retrying. |
Capture-agent uploads can also return the intake.* resumable-upload codes above.
Paperless migration and plugins
| Code | HTTP / retry | Meaning and safe action |
|---|---|---|
paperless.backend_unavailable | 501 / do not retry | The selected persistence backend does not implement this importer. Use the supported profile. |
paperless.invalid_request | 400 or 413 / do not retry | Import-creation JSON is malformed or oversized. |
paperless.invalid_upload | 400 / do not retry | Export-file metadata, ordinal, or workflow state is invalid. |
paperless.invalid_chunk_content_type | 415 / do not retry | The chunk must use application/offset+octet-stream. |
paperless.not_found | 404 / do not retry | The import is absent or outside household scope. |
paperless.state_conflict | 409 / backoff | Import state or offset changed. Read current status before retrying. |
paperless.chunk_too_large | 413 / do not retry | Split the file into smaller chunks. |
paperless.checksum_mismatch | 460 / backoff in current API | Re-read the offset and resend corrected bytes and checksum. |
paperless.unavailable | 503 / backoff | Migration persistence or service is unavailable. |
plugins.invalid_json | 400 or 413 / do not retry | Plugin request JSON is malformed or oversized. |
plugins.invalid_request | 422 / do not retry | Settings or command input does not match the installed descriptor. |
plugins.invalid_idempotency_key | 400 / do not retry | Supply one bounded command idempotency key. |
plugins.precondition_required | 428 / do not retry | Supply the current settings ETag. |
plugins.invalid_precondition | 400 / do not retry | If-Match is not one strong settings revision. |
plugins.stale_revision | 412 / do not retry | Reload settings and ETag, then reapply the intended change. |
plugins.command_conflict | 409 / do not retry | Command state or idempotency input conflicts. Read the existing run. |
plugins.unavailable | 503 / backoff | Plugin catalog or state is unavailable. |
Client decision pattern
- Handle the HTTP status as the coarse transport class.
- If the media type is
application/problem+json, branch oncodeand treattitleas display text. - For a known code, follow its precondition, state-refresh, or operator action before retrying.
- For an unknown code, follow
retryconservatively, retainrequestId, and preserve the response for diagnosis without logging secrets. - Treat a
200or202task, batch, upload, or capture-job payload as its own state machine; request success does not guarantee asynchronous processing success.
See the native API quickstart for a complete request flow and the generated operation reference for current schemas.