validation_failed
A field, query parameter or header has a value the endpoint can’t accept.
HTTP 400 · invalid_request_error · not retryable
What happened
Section titled “What happened”A field, query parameter or header has a value the endpoint can’t accept.
param names it, using dots for nested JSON members (items.0.amount). The pipeline sends it
for:
- an unknown JSON member (“
amoutisn’t a known field. Check the spelling, or the API version.”) - a JSON value of the wrong type (“
limithas the wrong type: it must be a whole number.”) - a
limitoutside 1–100, or acursorthis API didn’t issue
Renaming an agent is 422, with this code. Sending name in PATCH /v1/agents/{id} answers
422 validation_failed with param: "name": “Agent names can’t change, because policies match on
them. To rename, create a new agent with the new name and move its keys.” Names are immutable
because policies match on them (AGENTS.md).
The on-behalf-of headers are 422, with this code. A Deedglass-On-Behalf-Of or
Deedglass-Session header that doesn’t match ^[A-Za-z0-9._~:@/+=-]{1,256}$, or is sent twice,
answers 422 validation_failed with param set to the header name: “Deedglass-On-Behalf-Of must
be 1 to 256 characters: letters, digits and . _ ~ : @ / + = -. Use an opaque user id, not a name.”
(for Deedglass-Session: “… Use an opaque conversation or run id.”), or “Send
Deedglass-On-Behalf-Of once. It names one person or session per call.” It is checked on every
request an API key authenticates (IDENTITY.md, On-behalf-of).
The Gate’s checks. POST /v1/actions refuses a malformed request before anything is
recorded:
| Param | Message |
|---|---|
args |
args is 312 KiB; the limit is 256 KiB. Send a reference to the data instead of the data itself. |
args |
args is nested more than 32 levels deep. Flatten it, or send a reference to the data. |
args |
args contains an integer larger than 9007199254740991, which JSON can't carry exactly. Send it as a string. |
args |
args must be a JSON object. Send the tool's arguments as an object, {} when it takes none. |
tool |
tool is empty. Name a tool as "connector.tool", for example "fake.echo". |
mode |
mode must be gateway or proxy (got "{mode}"). Leave it out for gateway, where Deedglass runs the tool. |
wait |
wait must be a number of seconds from 0 to 25. |
connector_type |
connector_type is for proxy mode, where the edge runs the tool. In gateway mode Deedglass knows the connector; leave connector_type out. |
POST /v1/actions/{id}/result checks the edge’s report the same way: status (“status must be
succeeded, failed or unknown.”), the times, error_code, and result_digest, which must match
result (“result_digest doesn’t match result. Send the digest of the exact result (sha256 of its
RFC 8785 form), or leave it out.”). GET /v1/actions/{id} takes only wait (0 to 25 seconds,
sent once) and expand[].
Connector read-backs. Creating or updating a connector checks each write tool’s
readback and postcondition (CONNECTORS.md). param is the
field’s path in the config; when several fields are wrong, the message names the first and says
how many there are:
| Param | Message |
|---|---|
config.tools[1].readback.tool |
"update_status" writes, so it can't be a read-back. Name a read tool such as "get". |
config.tools[1].readback.tool |
"list" isn't idempotent, so it can't be a read-back. Name a read tool that is. |
config.tools[1].readback.attempts |
attempts above 1 need consistency: eventual. |
config.tools[1].postcondition |
A postcondition needs a read-back to read from. Add readback: { tool: get, args: … } to this tool. |
config.tools[1].postcondition |
1:28: request.status isn't a field. Did you mean args.status? |
config.tools[1].postcondition |
This condition could cost up to 520,488,451 units per call; the limit is 100,000. Compare fewer fields, or use expect. |
What to do
Section titled “What to do”Fix the field the message names, then retry.
Example
Section titled “Example”{ "error": { "type": "invalid_request_error", "code": "validation_failed", "message": "`limit` must be between 1 and 100.", "param": "limit", "request_id": "req_01j9zr3m5k8q2w7x4t6v0b1c9d", "doc_url": "https://docs.deedglass.com/errors/validation_failed" }}The message is for a person and can get more exact over time: branch on type and code, never on the message.
In the SDKs
Section titled “In the SDKs”| SDK | Raised as |
|---|---|
TypeScript (@deedglass/sdk) |
InvalidRequestError with code === "validation_failed" |
Python (deedglass) |
deedglass.InvalidRequestError with .code == "validation_failed" |