Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 30 Oct 2026. What's built · Install 0.1.0
jadpo
Reference: HTTP

HTTP

How failures reach the client

On this page

Every failure reaches the client in one envelope: code, message, request_id, and the failure's client fields under details (Failures). The status comes from the failure's kind, and the x-request-id header repeats the id.

Bad input lists each problem without its value. It names the field by its path in the Input, with list positions as numbers, the names the OpenAPI schema uses:

json
{  "error": {    "code": "invalid_input",    "message": "Request input is invalid.",    "request_id": "req_0b1e…",    "details": {      "problems": [        { "field": "lines.2.quantity", "rule": "max" },        { "field": "colour", "rule": "unknown_field" }      ]    }  }}

The runtime answers these itself, before or around what the route runs:

Condition Status and code
The body is not JSON, isn't sent as JSON (Content-Type), or the query string cannot be read 400 invalid_request
A header's value isn't printable ASCII 400 invalid_request
A field is missing, unknown or breaks a rule (body, query, header or placeholder), or the route reads no query string or body and one came 422 invalid_input
No route matches 404 route_not_found
The path exists but not for this method 405 method_not_allowed, with Allow
The body is over the limit 413 request_too_large
The deadline passed 504 deadline_exceeded
An Idempotency-Key is missing where the API requires one, or isn't 1 to 255 printable ASCII characters 400 invalid_request
An Idempotency-Key comes again with a different request 422 idempotency_key_reused
An Idempotency-Key comes again while its first request is running 409 conflict

When a repeat is the same request

A request with a key that came before is the same request when its route (its method and declared path) and what it says, decoded, are the same. What it says is each placeholder and the input: from the query string, the headers it reads and the body. The runtime writes these back through the route's own codecs as the contract's JSON, and keeps a digest of that.

That JSON writes every secret value (Password, BearerToken and the rest, see Standard library) as its kind alone. So the digest the runtime keeps says nothing of a secret, whether it came in the body or the path, and whoever can read the key table can't test guessed passwords against it. A repeat that differs only in a secret, or only in its JSON's spacing or member order, is the same request, answered as the first was.

A response that starts a session or carries a credential is never kept.

The digest isn't keyed (no secret is mixed into the hash), since a key would need a secret every deployment holds, and Jadpo has none (Configuration and time). So a value that isn't secret, sent and neither stored nor answered, can still be confirmed by guessing, by whoever reads the table. That person reads the kept responses and the application's own tables as well.

When the host has no clock

A deployable, a program jadpo build makes from the app such as a native server (Declared deployables), answers under its host's clock. When the clock can't be read (the system clock is before 1970), every request, health checks included, is 500 internal_fault and nothing runs. Its fault, for the host's log, says the host has no clock. jadpo dev doesn't start (cli.dev_start_failed, "The system clock can't be read").

Wording for people

The envelope's message stays fixed English. Text for people in client apps comes from the app's language files (Failures for client apps). Every failure a route can produce has wording in every supported locale, keyed by its code, with its client fields as placeholders. Client fields that are dates or numbers stay values on the wire, for the client to format in its own language.

Markdown for agents: /docs/how-failures-reach-the-client.md.Built from Jadpo main at a707efb.