Skip to content

raw Hono mounts (getRawApp()) answer an escaped throw as 500 text/plain "Internal Server Error" — no ADR-0112 envelope, declared status/code discarded #17411

Description

@os-justin

A route mounted through IHttpServer.getRawApp() funnels through neither the Hono adapter's wrap() nor any registrar wrapper, so an escaped throw there is answered by Hono's own default handler: 500 text/plain "Internal Server Error". No ADR-0112 envelope, no success flag, no code — and the thrown value's own declared status / code are discarded.

Split out of #16545 by the executing seat, at the domain:cli PM seat's explicit direction (comment 5570159125, restated in 5575064522):

raw Hono mount 在本卡范围之外,且必须在 PR 里写明,而不是默默略过。

and

⛔ Not filed by this note: the raw-mount defect itself (500 text/plain, no ADR-0112 envelope). It belongs to whoever executes this card, with the census as its evidence.

Measured, on origin/main + the #16545 fix

Both throws below were driven through one HonoHttpServer, the raw pair mounted exactly the way marketplace-install-local-plugin.ts mounts (getRawApp().get(...)), the wrapped pair through the ordinary IHttpServer verb:

/raw/envelope        -> 500  text/plain; charset=UTF-8
                        Internal Server Error
/raw/plain           -> 500  text/plain; charset=UTF-8
                        Internal Server Error
/wrapped/envelope    -> 503  application/json
                        {"success":false,"error":{"code":"SERVICE_UNAVAILABLE","message":"The authorization store could not be read."}}
/wrapped/plain       -> 500  application/json
                        {"success":false,"error":{"code":"INTERNAL_ERROR","message":"No response from handler"}}

/raw/envelope and /raw/plain are byte-identical. That is the measurement that made the seat rule the door out of #16545's scope: #16545's required pin — "a non-envelope throw still answers 500 with no cause in the body" — is green on this door before any fix exists, so writing it there would have measured nothing.

Why this is a contract violation and not a style note

BaseResponseSchema / ApiErrorSchema (ADR-0112) is the declared refusal envelope for this platform's HTTP surface. These doors are mounted on the same app, under the same prefix, and answer a shape no client parser can read — a caller doing body.error.code gets undefined, and a caller doing res.json() throws on Internal Server Error.

The door population (measured, getRawApp() consumers)

Not one door — the escape hatch has several consumers:

  • packages/cloud-connection/src/marketplace-install-local-plugin.ts (the census's exemplar)
  • packages/cloud-connection/src/marketplace-proxy-plugin.ts
  • packages/cloud-connection/src/cloud-connection-plugin.ts
  • packages/cloud-connection/src/runtime-config-plugin.ts
  • packages/metadata/src/plugin.ts (HMR routes)
  • packages/plugins/plugin-auth/src/auth-plugin.ts (wildcard routing)
  • packages/plugins/plugin-approvals/src/approvals-plugin.ts
  • packages/cli/src/utils/console.ts (two sites)

What is NOT being proposed here

⛔ Not "bring the raw mounts under wrap()" by default. The seat's own reasons against that stand and are worth carrying into whatever decision this card gets:

  1. Bringing a raw mount under the wrapper is a transport-level change with its own blast radius, and it is not in this card's named surface.
  2. The repo's working shape is route-level, not transport-level.

So this needs a decision on instrument before it needs an implementation: a Hono onError hook on the raw app, a shared catch helper each raw door opts into, or bringing the doors back onto IHttpServer. Each has a different blast radius and a different answer for the doors that deliberately want framework-native mounting.

Related


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions