Errors
Service errors have one shape: {"error": {"code", "message", "docs"}}. message is one sentence that says how to fix it, and docs links to the code's section on this page. The SDKs raise them as SignafaideError with the same code and message. A coding agent with the signafAIde MCP server can call signafaide_explain_error.
chain_conflict #
HTTP 409. The record's seq/prev does not follow the agent's head. Fetch GET /v1/heads/{agent} and re-chain from that head; the error body holds it.
With the SDK: The record's seq or prev does not follow the head the service holds for that agent, so the local chain and the service's chain differ. The SDK stops shipping that agent's records and never rewrites the local chain. Run signafaide status and signafaide verify to see where the chains part. The usual cause is two machines or two copies of .signafaide/ writing for the same agent name with the same key: give each its own agent name, or keep one .signafaide/ per project.
bad_signature #
HTTP 400. The signature does not verify, its key was not active at the record's time, or the key was revoked before the record arrived. A revoked key: give the agent a new key with signafaide keys rotate, then signafaide repair sets aside the records the old key signed after it ended. Sign sha256(JCS(envelope)) under domain 'record' with an active key registered for the agent. For POST /v1/agents: proof (domain 'register') and, when the agent has an active key, rotation (domain 'rotate') must verify.
With the SDK: A record's signature does not verify; its key was not active at the record's time, or was revoked before the service received it; or an agent registration's proof of possession or rotation signature is missing or wrong. Do not edit .signafaide/ by hand. If an agent key file in .signafaide/agents/ was replaced, restore it from backup. If the key was revoked, run signafaide repair --agent <name>: it sets aside the records the key signed after it ended (kept, still verifiable locally) and gives the agent a new key. To give an agent a new key otherwise, run signafaide keys rotate (the SDK signs the rotation with the old key), or have a developer or admin revoke the old key in the console first.
unknown_agent #
HTTP 400. Register the agent and its public key with POST /v1/agents before sending its records.
With the SDK: Records arrived for an agent whose key is not registered with the service. The SDK registers agents itself and retries once. If it persists, run signafaide flush and check that .signafaide/agents/<agent>.key exists.
content_mismatch #
HTTP 400. sha256(salt || JCS(content)) differs from envelope.content_hash. Hash the exact content you send, with its salt.
With the SDK: With store_content on, the content sent does not hash to the envelope's content_hash. Content must be JSON-serialisable and must not change after the call. Wrap the function so the SDK hashes the exact value it sends.
quota_exceeded #
HTTP 429. The monthly record quota is used up. Wait for the next period, or claim the sandbox / upgrade the plan. The SDKs keep the records and stop sending in the background until the API key changes; signafaide flush tries again.
With the SDK: The monthly record quota of this project is used up. Records stay in the local outbox and nothing is lost. The SDK stops sending in the background until the API key or SIGNAFAIDE_URL changes, so it never floods the service. Claim the sandbox (signafaide claim) and use a live key, or wait for the next month; then signafaide flush. signafaide status shows the quota.
plan_required #
HTTP 402. The organization's plan does not include this feature. The message names the plan that does and the console billing page where an owner or admin can upgrade.
With the SDK: The organization's plan does not include this feature, for example stored content on live records on Free. Records refused for it stay in the local outbox and nothing is lost. An owner or admin upgrades the organization on the console's Billing page (the message has the link), then run signafaide flush. Or turn store_content off to keep records hash-only.
invalid_key #
HTTP 401. Send Authorization: Bearer sfa_test_... or sfa_live_... with a key that is not revoked.
With the SDK: The API key is missing, malformed or revoked. Check SIGNAFAIDE_API_KEY in the environment or .env. Remove it and run signafaide init to create a new sandbox, or paste a live key from the console.
invalid_record #
HTTP 400. The request or a record breaks the §2 rules: the schema, the key's project and env in the envelope, a time at most 300 s ahead of the service clock and never before the agent's previous record, or a registration valid_from at most 7 days back and not in the future. A client clock that was ahead: fix the clock, then signafaide repair sets aside records written with future times. The message names the record and the rule.
With the SDK: A request or record breaks the rules of SPEC §2: a schema error (an agent name that is not lowercase, a name over 128 characters), an envelope for another project or env, a time more than 300 s ahead of the service clock or earlier than the agent's previous record, or a key registration with a valid_from more than 7 days back. The message names the record and the rule. Agent names match ^[a-z0-9][a-z0-9._-]{0,63}$; record names are 1 to 128 characters and never personal data. For time errors, fix the machine's clock (NTP); records already written with a time the witness cannot take make the chain BLOCKED, and signafaide repair sets them aside and starts a new segment.
rate_limited #
HTTP 429. Too many requests from this client. Wait for the Retry-After seconds and retry.
With the SDK: Too many requests from this client (sandbox keys and sandbox creation are rate-limited). Nothing to do: the SDK retries with backoff. For sustained volume, claim the project and use a live key.
not_found #
HTTP 404. The record, head or resource does not exist in this project and env.
With the SDK: The record, agent head or route does not exist in this project and env. Check the record hash or agent name, and that the API key belongs to the project that wrote it (a sandbox key and a live key are different projects).
bad_request #
HTTP 400. A query parameter or body field is invalid. The message names it.
With the SDK: A query parameter or request body (other than a record) is invalid. The message names the field. For signafaide export, --from and --to are RFC 3339 times.
unauthorized #
HTTP 401. Sign in to the console first (POST /api/auth/magic-link or GitHub).
forbidden #
HTTP 403. Your role in this organization does not allow this action. Ask an owner or admin.
reauth_required #
HTTP 403. Deleting a project, an organization or an account needs a sign-in from the last 15 minutes. Sign in again, then repeat the request.
conflict #
HTTP 409. The change conflicts with the current state, for example removing the last owner.
unavailable #
HTTP 503. The feature is not configured on this server, for example email delivery.
internal #
HTTP 500. The service hit an internal error. Retry, and report it if it persists.
Raised by the SDKs #
These never come from the service; the SDKs raise them as SignafaideError too.
network #
The service could not be reached. Records are kept in .signafaide/outbox/ and ship later; nothing is lost. Check SIGNAFAIDE_URL and the network, then run signafaide flush. Only strict mode waits for the service.
not_recorded #
Strict mode: the decision got no receipt from the service, so the function did not run. Fix the cause in the message (often network), then call again. Use strict mode only where an action must never run unrecorded.
no_receipts #
The service accepted a batch but returned no receipts matching it. Run signafaide flush again and signafaide verify. If it repeats, report it with the output of signafaide status.
bad_response #
The service answered with values the SDK refuses to use: an API key, project id or env that is not well formed, or receipts for another project. Nothing was written to .env or .signafaide/. Check SIGNAFAIDE_URL: it should be your signafAIde service, over https. A wrong URL in a cloned repo's .env is the usual cause.
state #
The local .signafaide/ state could not be used, for example a folder that cannot be written (a read-only disk), a damaged chain line or a lock held by another process. The message names the file. On a read-only disk, set SIGNAFAIDE_HOME to a writable folder (see the production guide), or SIGNAFAIDE_DISABLED=1 to turn recording off. Do not delete chain files: they are your evidence. Move a damaged line aside, then run signafaide verify.
key_mismatch #
The service has a different key registered for this agent name than the local key file. Another machine registered this agent name first. Use a different agent name here, or restore the original key file.
no_key #
Strict mode needs the service's receipt before the function runs, and there is no API key. Without a key records stay local and nothing is sent, so a strict call cannot proceed. A person opts in with signafaide init (a free sandbox, no account) or by setting SIGNAFAIDE_API_KEY (and SIGNAFAIDE_URL for a self-hosted witness). Or turn strict mode off for that tool.
too_old #
A chain written locally before the opt-in starts more than 7 days ago. The service accepts records only up to 7 days old (an agent key's valid_from is at most 7 days before its registration, spec §2.4), so that chain stays local. Nothing to repair: the local chain still verifies with signafaide verify, and new records of that agent start a new chain that ships. Opt in sooner next time.
chain_exists #
A chain written before the project was known cannot join the project, because that agent already has a chain there. It stays pending, on this machine only. Nothing to repair: it still verifies with signafaide verify. To ship such records, use a different agent name before opting in.