Error Code Registry

ACDP error codes returned in error envelopes (error.code). The envelope shape and HTTP status mapping are defined in RFC-ACDP-0007 §4–5.

v0.1.0 codes (plus 0.2.0 / 0.3.0 additions, marked)

CodeStatusHTTPMeaningSource
invalid_signatureStable400Signature verification failed.RFC-ACDP-0001 §5.8, RFC-ACDP-0003 §2.1
hash_mismatchStable400The body's content_hash (over ProducerContent) does not match the canonicalized body.RFC-ACDP-0001 §5.7
data_ref_hash_mismatchStable400A DataRef's bytes do not match the producer-declared data_ref.content_hash. Emitted by a registry at publish time for an embedded content_hash mismatch (RFC-ACDP-0002 §6.6 Check 8); also the semantic a consumer surfaces for an external-DataRef fetch mismatch (RFC-ACDP-0002 §6.5). Distinct from hash_mismatch (body-level) and invalid_signature — the body stays cryptographically valid; only the referenced data diverged.RFC-ACDP-0002 §6.5–§6.6, RFC-ACDP-0007 §5
schema_violationStable400Request body or query failed structural validation.RFC-ACDP-0003 §2.1
not_authorizedStable403Agent lacks permission for the operation. Call sites: supersession by a different agent_id (RFC-ACDP-0003 §3.1 step 3); unauthenticated read on a registry that does not advertise anonymous_public_reads (RFC-ACDP-0008 §6.3).RFC-ACDP-0003 §3.1, RFC-ACDP-0008 §6.3
not_foundStable404Resource not found.RFC-ACDP-0004 §7
superseded_targetStable400 / 409The supersedes target is invalid (any reason — details.reason provides specifics). HTTP 400 for static violations; HTTP 409 Conflict for race conditions (already_superseded, version_mismatch).RFC-ACDP-0001 §5.6.1, RFC-ACDP-0003 §2.1 steps 9–10, §3.1
unsupported_algorithmStable400Signature algorithm not in the registry's supported_signature_algorithms.RFC-ACDP-0001 §5.10, RFC-ACDP-0003 §2.1 step 5
rate_limitedStable429Per-agent rate limit exceeded.RFC-ACDP-0008 §4.3
payload_too_largeStable413Request body exceeds limits.max_payload_bytes.RFC-ACDP-0003 §2.1 step 2
embedded_too_largeStable413An embedded data reference exceeds 64 KB.RFC-ACDP-0002 §6.3, RFC-ACDP-0003 §2.1 step 3
key_resolution_failedStable400Permanent DID resolution failure: DID document parsed successfully but does not contain the requested key fragment; fragment is missing from key_id; or the producer DID resolves to a network target forbidden by SSRF policy (RFC-ACDP-0008 §4.8). Producer error; not retryable.RFC-ACDP-0003 §2.1 step 6, RFC-ACDP-0008 §4.8
key_resolution_unreachableStable502Transient DID resolution failure: DNS, TLS, HTTP non-2xx, or timeout while fetching the DID document. Retryable with backoff.RFC-ACDP-0001 §5.11, RFC-ACDP-0003 §2.1 step 6
key_not_authorizedStable403The DID portion of signature.key_id (everything before #) does not equal body.agent_id, or the resolved verification method is not in the DID document's assertionMethod.RFC-ACDP-0003 §2.1 step 6
not_implementedStable501The requested endpoint requires a profile this registry does not advertise (e.g., GET /contexts/search without acdp-registry-discovery). All acdp-registry-core endpoints are mandatory and MUST NOT return this code.RFC-ACDP-0001 §9.1, RFC-ACDP-0007 §4
cursor_expiredStable400A previously-issued pagination cursor is no longer valid. Client SHOULD restart pagination.RFC-ACDP-0005 §2.5.4
invalid_cursorStable400A pagination cursor is malformed or unrecognized.RFC-ACDP-0005 §2.5.4
duplicate_publishStable409An idempotent publish was retried with conflicting content (same Idempotency-Key, different content_hash).RFC-ACDP-0003 §6.2
cross_registry_resolution_failedStable502A cross-registry resolution failed (DNS resolution refused by IP-range filter, response oversize, timeout, redirect-policy violation, or upstream registry unavailable). See RFC-ACDP-0006 §7.RFC-ACDP-0006 §7
internal_errorStable500Unexpected registry error. The standard envelope MUST be used; error.message MUST NOT leak stack traces or sensitive context. Retryable.RFC-ACDP-0007 §4
invalid_log_proof (0.3.0)Stable502A transparency-log artifact failed the RFC-ACDP-0012 §9 verification procedures: an inclusion proof whose folded audit path does not reproduce the checkpoint’s root_hash, a consistency proof that fails between two tree sizes of the same log_id, or a checkpoint whose signature does not verify over the recomputed preimage. Deliberately distinct from invalid_receipt — a proof failure indicts the log (tree membership, history consistency, checkpoint signature), not the receipt, and the two verdicts are independent (RFC-ACDP-0012 §9.3); collapsing them would overload a single semantic. On the wire it is emitted by a federated resolver (or any registry validating an upstream’s proofs on a caller’s behalf) — the upstream is at fault, hence 502; it is also the verification-failure category consumer SDKs use for locally failing proofs. Malformed proof requests are schema_violation; an unlogged or invisible ctx_id on GET /log/proof is not_found; there is deliberately no log_unavailable (registries advertising acdp-registry-transparency-log MUST always log and serve proofs, RFC-ACDP-0012 §7). MUST NOT be emitted by implementations declaring acdp_version < 0.3.0.RFC-ACDP-0012 §9, §11
invalid_witness_cosignature (0.4.0)Proposed502A transparency-log witness cosignature failed the RFC-ACDP-0015 §8 verification procedure: a closed-schema parse failure, a witness-key signature that does not verify over the recomputed cosignature preimage, a signature.key_id whose DID portion ≠ witness_id, a witnessed_checkpoint tuple that does not match the checkpoint being evaluated, or a future-dated witnessed_at beyond the skew allowance. Deliberately distinct from invalid_log_proof — a cosignature failure indicts a witness's attestation (an independent signer), not the registry's log (tree membership, consistency, checkpoint signature); the two verdicts are independent (RFC-ACDP-0015 §8, RFC-ACDP-0012 §9.3), and collapsing them would overload a single semantic (same argument that kept invalid_log_proof distinct from invalid_receipt). On the wire it is emitted by a registry aggregating cosignatures, or a resolver validating a witness's cosignatures, on a caller's behalf — the upstream party is at fault, hence 502; it is also the verification-failure category consumer SDKs use for a locally failing cosignature. A merely stale (but valid) cosignature is consumer freshness policy, not this code; an un-witnessed (0-witnessed) checkpoint is not an error. MUST NOT be emitted by implementations declaring acdp_version < 0.4.0. Fixture wit-004.RFC-ACDP-0015 §8, §10
immutable_field (0.3.0)Stable400A lifecycle (or any future mutation) endpoint request attempted to supply or alter immutable body content (e.g. a body member or a body-field-named member on POST /contexts/{ctx_id}/retract). Bodies are immutable; lifecycle endpoints mutate registry state only. Activated from the reserved-codes table below (reserved since v0.1.0 per RFC-ACDP-0009 §2.1); distinct from schema_violation so producers learn the category error. MUST NOT be emitted by implementations declaring acdp_version < 0.3.0. Not retryable. Fixture lc-002.RFC-ACDP-0013 §6, §10
invalid_lifecycle_transition (0.3.0)Stable409The requested lifecycle transition conflicts with the context's current retraction state: retract of an already-retracted context, or republish of one not retracted (RFC-ACDP-0013 §6 step 4 — strict retracted/republished alternation). A state conflict, like the 409 arm of superseded_target; retryable only after the state changes. MUST NOT be emitted by implementations declaring acdp_version < 0.3.0. Fixture lc-001 scenario C.RFC-ACDP-0013 §6, §10
invalid_receipt (0.2.0)Stable502A registry receipt failed the RFC-ACDP-0010 §8 verification procedure. On the wire it is emitted by a federated resolver (or any registry validating an upstream receipt on a caller's behalf) — the upstream registry is at fault, hence 502. It is also the verification-failure category consumer SDKs use in their own diagnostics for a locally failing receipt; in that use the accompanying body's verdict is independent (the producer signature may still verify). There is deliberately no receipt_unavailable: registries advertising acdp-registry-receipts MUST always mint (RFC-ACDP-0010 §7). MUST NOT be emitted by implementations declaring acdp_version 0.1.0. (0.3.0) Also the failure category for lineage-head receipts failing the RFC-ACDP-0011 §7 procedure — RFC-ACDP-0011 deliberately introduces no new wire code (its §9); as_of staleness within the past is consumer freshness policy, not a wire error.RFC-ACDP-0010 §8, §11, RFC-ACDP-0011 §7, §9

Note: visibility_denied is an internal-only signal (logging/metrics). Visibility denial is always reported externally as not_found per RFC-ACDP-0008 §4.5. The wire-visible enum in acdp-error.schema.json does NOT include visibility_denied.

Reserved future codes

These codes are NOT in the v0.1.0 wire schema enum. They are reserved for future ACDP versions and MUST NOT appear in v0.1.0 wire responses.

CodeReserved forReference
unsupported_embedding_modelA future version's similarity endpoints. ACDP v0.1.0 has no similarity surface.RFC-ACDP-0009 §2.9

(0.3.0) immutable_field — reserved here since v0.1.0 for "a future version's mutation endpoints (retraction, attestation updates)" — was activated by RFC-ACDP-0013 and moved to the main table above, exactly as invalid_receipt graduated in 0.2.0.

superseded_target reason codes

When returning superseded_target, registries SHOULD include details.reason to disambiguate. Defined values:

details.reasonMeaning
not_foundThe supersedes target does not exist.
lineage_mismatchThe new context's computed lineage_id ≠ the superseded context's lineage_id.
version_mismatchThe new context's versionprevious.version + 1.
already_supersededAnother context already supersedes the target.
cross_registry_supersession_unsupportedRegistry does not support cross-registry supersession.
lineage_walk_failedThe registry could not retrieve an intermediate context while walking back through supersedes to compute lineage_id. See RFC-ACDP-0001 §5.6.1.

Adding a code

Open a PR adding a row to the table above. Codes MUST:

  • Be lowercase snake_case.
  • Not collide with existing entries.
  • Be implementable by both registries and consumers (registries emit; consumers handle).
  • Carry a single semantic — no overloading. If an existing code already covers the case, reuse it with details.

Information leakage rule: error.message is informational only and MUST NOT be used in automated decisions. Registries MUST NOT distinguish "not found" from "not authorized" externally for visibility-restricted contexts.