Validation
DaloyJS validates inputs through Standard Schema, a tiny interface exposed by validators such as Zod, Valibot, ArkType, and TypeBox via a Standard Schema adapter. Pick the validator that fits your project; the DaloyJS contract is the same.
What gets validated
For each route you can declare schemas for:
request.params: decoded path parameters. They start as strings; coerce in your schema if you want numbers, UUIDs, or enums.request.query: query string values. Repeated keys become arrays before validation.request.headers: request headers as lower-case names.request.body: parsed request bodies. The body is only read when a route declares a body schema.responses[status].body: typed and validated response bodies.
Query strings, form fields, and multipart fields drop prototype pollution keys such as __proto__, constructor, and prototype before validation.
End-to-end example
Pick your validator
- Zod: the default for most teams. Chainable API, large ecosystem, easy to learn.
- Valibot: modular and tree-shakeable. Great for edge runtimes and browser-shipped contracts.
ArkType and TypeBox-compatible schemas also work when they expose the same ~standard property, but DaloyJS only ships first-party docs and scaffolds for Zod and Valibot.
Side-by-side
Once a schema exposes ~standard, DaloyJS infers handler types, generates OpenAPI, and returns problem+json errors the same way regardless of which validator produced it.
Errors
- untrustedRaw requestparams · query · headers · body
- standard schemaSchema parsevalidate(schema, input)
- on failure422 problem+jsonerrors: [{ path, message }]
- on successTyped handlerctx.body / params / query / headers
On invalid input, DaloyJS returns 422 Unprocessable Entity as RFC 9457 problem+json with an errors array of per-issue path and message records. You don't write an error handler for this, it's built in. See Errors & problem+json.
Response validation
When a response schema is declared, DaloyJS validates the handler return before serializing it. The validated value is what goes on the wire, so object schemas that strip unknown keys also prevent undeclared fields from leaking to clients. If validation fails, the client receives a redacted 500 problem response in production.
Body limits and content types
When a route declares request.body, DaloyJS also enforces:
- Content-Length and streamed size against
app.bodyLimitBytes→ 413. - Content-Type against the route's
acceptslist, or globalallowedContentTypesif set → 415. - Default accepted body types:
application/json,application/x-www-form-urlencoded, andmultipart/form-data. - Prototype-pollution-safe parsing for JSON, query strings, urlencoded forms, and multipart forms.
JSON bodies parse to objects, urlencoded bodies parse through URLSearchParams, and multipart bodies parse through the platform Request.formData() API. If you opt a route into a custom text media type, DaloyJS passes the decoded text into your body schema.
Mixing validators
You can mix and match per route. A Zod schema in one file and a Valibot schema in another are both valid, useful when migrating an existing codebase or consuming schemas from a shared package.