Skip to content

runtime: a declared 5xx carrying NO code keeps its prose on /analytics/query where /data withholds it unconditionally #12281

Description

@os-trump

Found while implementing #11718 (draft PR #12280), which aligned /analytics/dataset/query's declared-5xx arm to /data's. Out of scope there: that card is fenced to the analytics dataset arm in packages/rest, and this is a different door in packages/runtime.

⚠️Derived from source, not driven end-to-end. Recorded as a code-read so the next reader does not have to re-derive it; the first step on this card should be to measure it against a real mounted route, the way analytics-query-read-scope-withhold.test.ts already does for the code half.

The divergence

The two doors disagree on which declared 5xx gets its prose withheld.

packages/rest/src/error-response.ts — the /data arm (now shared as declaredServerFaultAnswer, PR #12280) withholds the message for any declared 5xx, whether or not a code rides along:

if(declaredStatus>=500){return{status: declaredStatus,body: {error: INTERNAL_ERROR_MESSAGE, ... }};}

packages/runtime/src/dispatcher-plugin.tserrorResponseBase, which /analytics/query and the other dispatcher exits use, gates the withhold on declaresServerFaultor a phrasing heuristic:

constmessage=declaresServerFault(err)||(httpStatus>=500&&looksLikeInternalErrorLeak(raw))
? INTERNAL_ERROR_MESSAGE
: raw||'Internal Server Error';

declaresServerFault is status >= 500and a non-empty string code (packages/types/src/error-leak.ts). So a producer that declares { status: 503 } with no code, and whose message does not sound like a driver dump, has its prose shipped to the caller here and withheld one door over.

Why this is the same class #5811 closed, one case narrower

#5811's own argument is that looksLikeInternalErrorLeak is a heuristic over SQL/driver phrasing, so it closes an exit only against faults that sound like a driver — measured, all eleven read-scope-sql shapes return FALSE from it. That is precisely why the withhold was made structural (declaresServerFault) rather than left to the heuristic. But the structural half requires a code, so the no-code half of the declared-5xx band still falls back to exactly the heuristic #5811 found insufficient.

error-response.ts documents the no-code case deliberately for the code field ("a half-declaration is honoured for the half that was declared and nothing is invented for the half that was not") — that reasoning is about inventing a code, and does not obviously extend to shipping the prose.

Not established here

Region: packages/runtime/src/dispatcher-plugin.ts, errorResponseBase's message ternary only.

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions