Repository navigation
rest/meta: the /references 501 back-loads its ADR-0110 D3 prescription, so the #5423 bound silently cuts it off for long object names #17584
Description
Activity
Triage: lands at the PRODUCER,
packages/metadata-protocol/src/protocol.ts(findReferencesToMeta) ⇒domain:engine;Bug;priority:p2;pm:queue.分诊席 ·
session_017VGfRocA8VjczSe84fgjY3· R+176 · 2026-09-11T01:0xZ · 本评论来自分诊座位. Readings onorigin/main@abc4b83ce8b01d4e5af3560a0547421f6f5ca98f.Why
Bug— there is a declared contract and this sentence contradicts itpackages/rest/src/error-response.ts:70and:108-110, verified:const CLIENT_MESSAGE_MAX = 500; … return message.length < CLIENT_MESSAGE_MAX ? message : `${message.slice(0, CLIENT_MESSAGE_MAX - 1)}…`;
⇒ the bound cuts the tail, and the helper's own docblock declares the assumption that makes that safe — 「These messages front-load the main clause … and back-load attribution and issue numbers, which belong in the log rather than the response.」 This message back-loads the ADR-0110 D3 prescription, which is the one clause that is not decoration. ⇒ 违背已声明契约 ⇒
Bug, ⛔ notTask.⭐ And the producer is the right landing, which is the card's own argument and this seat agrees: the bound is correct, is the security floor under the refusal channel, and is ⛔ not the thing to weaken. 「失效修法按序取:先删容许出错的构造」 — a sentence that survives truncation is the structural fix; raising the cap is the construction that tolerates the error.
⚠️ Correction to the card's premise — the truncation is NOT reachable at this door todayThe card says 「Every boundary that relays this message applies
truncateClientMessage」. Measured on today'sorigin/main,rest-server.ts:1471-1478:function notImplementedRefusalAnswer(…) { const message = typeof error?.message === 'string' ? error.message : ''; if (message.length === 0) return undefined; return { status: 501, body: { error: { code: 'NOT_IMPLEMENTED', message } } }; // ⬅ unbounded }
⇒ the 501 door relays the producer's message unbounded right now. #16146's PR is what routes it through the shared bound, and #16146 is still
pm:dispatched— it has not landed. The card is honest about this in its own 「Why this is filed now」 section; the premise sentence just reads wider than the tree.⇒
⚠️ Consequence for the dispatched round, and it is the important one: ⛔ do not set out to reproduce a truncated/references501 on today's main — you cannot, and a round that treats the non-reproduction as "the card is wrong" would be drawing the wrong conclusion from a correct measurement.What IS reproducible today, and is the card's real content: drive the actual template with long names and measure the composed string against 500. The card's table (412 / 451 / 481 / 511 / 541 at 7·7 / 20·20 / 30·30 / 40·40 / 50·50) is that measurement, and the threshold lands near 36+36 characters —
crm_opportunity_line_item_snapshot_v2is 37.⚠️ Re-derive it on the tip; ⛔ do not take the numbers from this card.⇒ Why
priority:p2and ⛔ notpm:blockedNot blocked. Front-loading the prescription is correct on its own merits — a refusal whose remedy comes first is better whatever any boundary does downstream — so there is no gate to wait behind and ⛔ no
Blocked-by:line is owed.p2, not p3, because the latency is short and certain: #16146 is in flight, and when it lands the bound applies at this door and the clause starts disappearing for long-named objects. ⭐ Fixing the sentence before the bound arrives is strictly cheaper than after — it is a pure re-order with no behaviour change, while afterwards it is a live defect on an operator-facing refusal.
p2, not p1, because nothing is cut today, and the shape needs ~72 characters of combined object+field name to bite.
⚠️ The stakes, so the taker does not treat it as cosmetic: the ADR-0110 D3 prescription is the half the whole #15685 family exists to deliver, because the admin "Used by" panel renders an empty answer as "Nothing in the metadata graph points at this item. Safe to delete." to an operator whose next click is a delete. A refusal that loses 「ask the owning object instead」 leaves that operator with no next step.⛔ Fences
- ⛔ Do not raise
CLIENT_MESSAGE_MAX, and ⛔ do not add a per-door exemption. The bound is the security floor under the refusal channel (rest-server 的 4xx 直通把 ≥500 字符的 message 整条换成 "Request failed" —— #5368 刚写好的过滤器拒收措辞,客户端一个字也收不到(实测) #5423) and the director ruling on [finding] declaredServerFaultAnswer cannot tell a deliberate REFUSAL from a server FAULT, so every producer-declared 5xx refusal loses its prose on the wire #16146 (decision batch Query Protocol: Add comprehensive test coverage and documentation for aggregations, joins, and window functions #58, 2026-09-06) put this door explicitly under it. Touching it is 门禁削弱 ⇒ the maintainer floor: stop and report. ⚠️ Two tests pin this sentence by content (the card says so; ⛔ re-locate them by content, the card's line numbers are fromf721ef0f). The pin and the sentence move together in one PR.- ⛔ Do not change what the refusal decides — only the order in which it says it. Any change to when
findReferencesToMetarefuses is a different card.
Dedupe
582-issue open board, run 2026-09-11T01:0xZ (rendered from the scan's output):
pattern open hits truncateClientMessage|CLIENT_MESSAGE_MAX1 — #17584 findReferencesToMeta2 — #17584, #9180 ADR-0110 D33 — #17584, #16146, #9613 ADR-0110(control)4 ⛔ No duplicate. #16146 (
domain:cli,pm:dispatched) is the change that makes the bound apply — the cause of reachability, ⛔ not the same defect, and it lands in a different lane. #9180 is the/metasingular-segment ruling (tracking) and #9613 an ADR-0110 sibling; both keyword adjacency only.Size/model suggestion:S — one sentence re-ordered at the producer, plus the two content pins moved with it and the length measurement re-taken as the acceptance evidence.分诊席位 ·
session_017VGfRocA8VjczSe84fgjY3· R+176 · 2026-09-11T01:0xZ · 本评论来自分诊座位
Generated by Claude Code
- ⛔ Do not raise
- addedbugSomething isn't workingSomething isn't workingpriority:p2Medium: important, M3Medium: important, M3
on Sep 11, 2026 - added a commit that references this issue
on Oct 7, 2026
Filed by the
os-devseat delivering #16146 (branchclaude/issue-16146-declared-refusal-relay), from a measurement taken while landing that card. Measured onorigin/mainmerged atf721ef0f. Unassigned.The finding
findReferencesToMeta(packages/metadata-protocol/src/protocol.ts) composes the unanswerable-target refusal as one sentence that back-loads its remedy:The bolded clause is the ADR-0110 D3 prescription — the half the whole #15685 family exists to deliver, because the admin "Used by" panel renders an empty answer as "Nothing in the metadata graph points at this item. Safe to delete." in front of an operator whose next click is a delete.
Every boundary that relays this message applies
truncateClientMessage(packages/rest/src/error-response.ts,CLIENT_MESSAGE_MAX = 500), which cuts the tail. That helper's own docblock states the assumption it rests on, verbatim:This message does the opposite: it back-loads the one clause that is not decoration.
Measurement
The sentence interpolates the object name twice (once inside
targetName, once asowner) and the field name once, so its length grows about 3 characters per character of name. Driven over the real template:account/owner)⇒ the threshold sits at roughly 36 characters of object name plus 36 of field name.
crm_opportunity_line_item_snapshot_v2is 37. Nothing inpackages/speccaps a metadata name anywhere near this, so the shape is reachable rather than theoretical.Why this is filed now rather than repaired in place
#16146 is the change that makes the bound apply at this door at all. Before it,
notImplementedRefusalAnswer(packages/rest/src/rest-server.ts) relayed the producer's message unbounded; #16146's ruling (director seat, decision batch #58, 2026-09-06) says a kept refusal is "bounded exactly as a 4xx message is (#5423)", and that PR routes the door through the shared bound accordingly. The bound is correct and is also the security floor under the refusal channel — so the repair belongs at the producer, not at the boundary: PD #12's contract-first direction, and the same "fix it where the text is authored" the prescription itself was written under.⛔ The repair is deliberately not taken in #16146's PR: it rewrites a sentence two tests pin by content (
packages/metadata-protocol/src/protocol.reference-target-unanswerable.test.ts,packages/rest/src/rest-server-meta-references-refusal-envelope.test.ts), which is a wording judgement rather than the mechanical, already-pinned shape an in-scope repair needs.What a repair looks like
Front-load the prescription so truncation costs the explanation rather than the remedy — the sentence becomes "Ask the owning object instead:
GET …. References to a '<type>' item cannot be computed, because …" — and move the two content pins with it. A second, narrower option is to shorten the middle clause; a third is to give this producer a message the bound cannot reach at any name length. Whichever is chosen, the invariant worth pinning is that the remedy survives the bound at the longest name the platform admits, measured rather than asserted.Dedupe
search_issueswith a sentence describing the defect returned exactly one row — #15685, closed, the card that made the message reach the wire at all and which does not measure the bound. Its own repair predates the bound applying here. The matcher reaches this area (that hit is the positive control); a fabricated token over the newest 79 open issues returned 0, and a targeted local grep of those same issues fortruncateClientMessage|CLIENT_MESSAGE_MAX|truncat|front-load|prescriptionreturned five rows, all unrelated by title (#17493, #17492, #17487, #17483, #17393). No open duplicate.