In these docs

Execution Layer for Odoo

Error codes.

Every failure the Execution Layer returns is a structured, machine-readable code, never prose. This is the reference: the codes grouped by kind, the three that carry a Context Layer hint, and the fields every refusal returns.

Feature-complete · Odoo 19 Updated 17 August 2026

The Execution Layer never returns a prose-only error. Every failure is a code an agent can branch on and a person can act on. The authoritative registry is error-codes.json in the product; the codes are grouped below by kind.

Request: the call was malformed or ambiguous

CodeMeaning
INVALID_ARGUMENTAn argument is missing or the wrong type.
SCHEMA_VIOLATIONThe payload failed the fail-closed schema check.
FIELD_UNKNOWNA field named in the call does not exist on the model.
FIELD_REQUIREDA field required for AI writes was not provided.
AMBIGUOUS_TARGETA human reference matched more than one record; candidates are returned.
UNRESOLVED_REFERENCEA human reference matched no record.
IDEMPOTENCY_KEY_REQUIREDA write was sent without its idempotency key.
LIMIT_EXCEEDEDA read or export exceeded the allowed size.

Policy: the action was not allowed

CodeMeaning
MODEL_FORBIDDENThe model is out of scope for this bundle or connection.
FIELD_FORBIDDENThe field is hidden or read-only for MCP.
PERMISSION_DENIEDOdoo’s own access rules deny it for this user.
TOOL_NOT_AVAILABLEThe tool is not in this user’s bundle.
ACTION_NOT_ALLOWLISTEDThe execute_action method is not on the allowlist.
PRECONDITION_FAILEDA declarative business rule was not satisfied.
APPROVAL_REQUIREDA risk-classed action was staged; a person must approve it.
APPROVAL_PENDINGThe approval request exists and is awaiting a decision.
APPROVAL_STALEThe payload changed after approval; the token is invalid.
APPROVAL_DENIEDA person declined the action.
EXPORT_DISABLEDExport is off for this bundle.
RATE_LIMITEDA per-key or per-user rate limit was hit.

State: the world did not match

CodeMeaning
MODEL_NOT_FOUNDThe model does not exist.
TARGET_NOT_FOUNDThe target record does not exist.
CONSTRAINT_VIOLATIONAn Odoo constraint rejected the change.
ASSERTION_FAILEDAn only_if assertion did not hold.
IDEMPOTENCY_CONFLICTThe same key was reused with a different payload.
PARTIAL_RESULT_REFUSEDA partial result was refused rather than returned as complete.
BATCH_ITEM_FAILEDAn item in an atomic batch failed; the batch rolled back.
VERIFICATION_FAILEDThe post-commit read did not match the declared intent.
CONTEXT_DEGRADEDThe Context Layer is degraded; the pipeline continued without it.

Server: something went wrong underneath

CodeMeaning
TIMEOUTThe operation exceeded its time budget.
COMMIT_FAILEDThe transaction could not commit.
AUDIT_UNAVAILABLEIn strict mode, the audit write failed, so the call failed.
INTERNALAn unexpected internal error.

The three honest-absence codes

Only three codes ever carry a one-line, factual hint that the Context Layer could help: AMBIGUOUS_TARGET, UNRESOLVED_REFERENCE, and FIELD_UNKNOWN. The hint is a status, never promotional prose injected into a response.

What a refusal returns

Every refusal, including a denial, is audited and returns a structured object with the machine code, a detail payload (for example the candidate list on AMBIGUOUS_TARGET), a human sentence, and, where the fix is a policy change, a fix_location pointing at the bundle or precondition to adjust.

See troubleshooting for what to do about the common ones.