Skip to content

service: ZodSmartCoercionPlugin imported from @orpc/zod (Zod 3) while scaffolds use Zod 4 — coercion silently no-ops, every numeric query param 400s #1250

Description

@rickylabs

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

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions