62ff152642
Effect's default Respondable for HttpApiSchemaError returns 400 with an empty body. The renderer / SDK / curl get nothing actionable — just "GET /url → 400 Bad Request: (empty response body)". When a real user hit this on Windows yesterday (corrupted DB row → schema rejected the response), we spent ~an hour reverse-engineering the cause from the URL alone. PR #26457 previously tried to surface the reason in a structured body ({data, errors, success}) and got reverted in #26546 because some plugins broke. The proximate cause was the SDK throwing raw POJOs to plugins instead of Errors, which has since been fixed by `wrapClientError` (`50dcc4f1a`). Use the same NamedError shape every other 4xx/5xx in this API already uses (e.g. NotFoundError 404): {"name":"BadRequest","data":{"message":"...","kind":"Body"}} The SDK's wrapClientError extracts data.message automatically, so any caller that handles existing 404 NotFoundError bodies handles this identically — no new contract. Verified end-to-end: BEFORE status: 400 body: "" SDK Error.message: opencode server GET .../message?... → 400: (empty response body) AFTER status: 400 body: {"name":"BadRequest","data":{"message":"Expected number, got null at [0][\"parts\"][0][\"tokens\"][\"output\"]","kind":"Body"}} SDK Error.message: Expected number, got null at [0]["parts"][0]["tokens"]["output"] Includes a regression test that asserts the body shape on a real Body schema rejection (POST /sync/history with invalid aggregate).