The scaffolded API docs page sends query parameters as strings, but the generated contract validates them as numbers — so the documented GET request fails with a 400 straight out of the box, using the docs page's own default value.
Reported by the maintainer on a fresh clone, following the docs.
Reproduction
Open the scaffolded API docs (/api/docs), select GET /issues/board, leave the pre-filled cycleId=1, press Send.
GET http://localhost:60746/api/issues/board?cycleId=1
30ms 230 B 400 Bad Request
{
"defined": false,
"code": "BAD_REQUEST",
"status": 400,
"message": "Input validation failed",
"data": { "issues": [ {
"expected": "number",
"code": "invalid_type",
"path": ["cycleId"],
"message": "Invalid input: expected number, received string"
} ] }
}
Why this matters more than a cosmetic bug
The API docs page is the first interactive surface a developer touches — it is how you confirm the backend you just scaffolded actually works. Right now the first request you can possibly make fails, and the error blames your input for a value the page itself supplied.
It also undermines the surface agents are being pointed at: #1204 added OpenAPI introspection read tools precisely so agents stop hand-rolling curl. If the documented request shape produces a 400, an agent that follows it concludes the endpoint is broken and goes back to curl — which is the behaviour we are trying to eliminate.
Cause
Query parameters arrive as strings over HTTP. The contract schema declares cycleId as a number and validation runs without coercion, so a numeric path parameter can never be satisfied through the docs client.
Either the generated schema should coerce query params, or the docs client should send typed values — but the two must agree, because today the scaffold ships them disagreeing.
Acceptance
The scaffolded API docs page sends query parameters as strings, but the generated contract validates them as numbers — so the documented
GETrequest fails with a 400 straight out of the box, using the docs page's own default value.Reported by the maintainer on a fresh clone, following the docs.
Reproduction
Open the scaffolded API docs (
/api/docs), selectGET /issues/board, leave the pre-filledcycleId=1, press Send.{ "defined": false, "code": "BAD_REQUEST", "status": 400, "message": "Input validation failed", "data": { "issues": [ { "expected": "number", "code": "invalid_type", "path": ["cycleId"], "message": "Invalid input: expected number, received string" } ] } }Why this matters more than a cosmetic bug
The API docs page is the first interactive surface a developer touches — it is how you confirm the backend you just scaffolded actually works. Right now the first request you can possibly make fails, and the error blames your input for a value the page itself supplied.
It also undermines the surface agents are being pointed at: #1204 added OpenAPI introspection read tools precisely so agents stop hand-rolling
curl. If the documented request shape produces a 400, an agent that follows it concludes the endpoint is broken and goes back tocurl— which is the behaviour we are trying to eliminate.Cause
Query parameters arrive as strings over HTTP. The contract schema declares
cycleIdas a number and validation runs without coercion, so a numeric path parameter can never be satisfied through the docs client.Either the generated schema should coerce query params, or the docs client should send typed values — but the two must agree, because today the scaffold ships them disagreeing.
Acceptance
GETendpoint no longer fails on parameter coercion (scope clarified 2026-08-04 during composed verification: list+health 200 with numeric defaults; by-id reaches the handler — its 500 on a missing row is service: generated by-id handler returns 500 {defined:false} for a missing row instead of a defined 404 #1263, and the empty "seeded" table is scaffold: db seed is a placebo — SELECT 1 plus a success banner, no rows seeded #1262, both outside this fix)handlers_test.tsevidence in PR #1256