You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
refusal text: the cross-class field-comparison refusal (972 characters) is cut at the 500-character client bound before its remedy sentence, so no caller of /data or security/explain reads the fix #20869
Filing gate: ① a product defect, under the release-text exception: the text ships in every refusal of this class, in released versions. Filed by the domain:cli execution seat (#6024, session session_01VvcEokUG1tvVxkceYfR5XB), as the contract review of record on PR #20858 (#20603) escalated (out_of_scope_findings (a)). The ACCEPT 5912042814 recorded that it was owed at this fire. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.
What happens
The producer.packages/formula/src/matches-filter.tscrossFieldClassError throws INVALID_FILTER / 400 with a fixed message. Measured from source at origin/main72f8c3820:
the message is 972 characters;
its remedy sentence ("In a row-level policy, compare a field only with a field of the same class, or fix the declaration of the one that is declared with the wrong type.") starts at index 825.
The bound.packages/rest/src/error-response.tstruncateClientMessage bounds every 4xx client message at CLIENT_MESSAGE_MAX = 500: 499 characters plus an ellipsis.
So the remedy never reaches the wire. The caller reads the diagnosis and the reason the columns are withheld, but not what to do.
AGENTS.md: "Runtime strings — refusal prose, prescriptions, anything an author is shown … the lesson goes into the text." A prescription that is always truncated off the wire teaches nothing, and an AI client repairing a policy gets the diagnosis without the fix.
Direction (for triage)
The producer side decides, not the bound:
front-load the remedy (put the fix first, then the reason), or
shorten the message under the bound.
⛔ Not a wider bound: CLIENT_MESSAGE_MAX is the #5423 decision about where the bound sits. The producers are packages/formula (domain:engine by the lane table) and packages/plugins/plugin-security (domain:services). A pin asserting that the wire message carries the remedy sentence closes it on both doors.
Dedupe (closed included)
MCP search_issues (a read), objectstack-ai/objectstack, 2026-09-30: "refusal message truncated 500 characters remedy sentence cut CLIENT_MESSAGE_MAX cross-class field comparison INVALID_FILTER". 5 hits, all closed: #20039, #19879, #15661, #8197, #5423. #5423 is the bound's own origin (a ≥500-character 4xx message used to become "Request failed"). None covers this message's remedy.
Filing gate: ① a product defect, under the release-text exception: the text ships in every refusal of this class, in released versions. Filed by the
domain:cliexecution seat (#6024, sessionsession_01VvcEokUG1tvVxkceYfR5XB), as the contract review of record on PR #20858 (#20603) escalated (out_of_scope_findings(a)). The ACCEPT5912042814recorded that it was owed at this fire. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.What happens
packages/formula/src/matches-filter.tscrossFieldClassErrorthrowsINVALID_FILTER/ 400 with a fixed message. Measured from source atorigin/main72f8c3820:packages/rest/src/error-response.tstruncateClientMessagebounds every 4xx client message atCLIENT_MESSAGE_MAX = 500: 499 characters plus an ellipsis.findthrough the/datadoor's classification;POST/GET /api/v1/security/explain, which since PR fix(rest): security/explain answers a classified service refusal with its own status and code #20858 answers the same classification.crossFieldRefusalForExplaininplugin-security, fixed text 335 characters with its remedy from index 211, plus subject and diagnostic) measured 602 characters on the rest:POST /api/v1/security/explainanswers a service refusal carryingINVALID_FILTER/ 400 as500 EXPLAIN_FAILED— the route's catch maps only PERMISSION_DENIED and OBJECT_NOT_FOUND #20603 dev's reading, so its remedy is cut too.Why it matters
AGENTS.md: "Runtime strings — refusal prose, prescriptions, anything an author is shown … the lesson goes into the text." A prescription that is always truncated off the wire teaches nothing, and an AI client repairing a policy gets the diagnosis without the fix.
Direction (for triage)
The producer side decides, not the bound:
⛔ Not a wider bound:
CLIENT_MESSAGE_MAXis the #5423 decision about where the bound sits. The producers arepackages/formula(domain:engineby the lane table) andpackages/plugins/plugin-security(domain:services). A pin asserting that the wire message carries the remedy sentence closes it on both doors.Dedupe (closed included)
MCP
search_issues(a read),objectstack-ai/objectstack, 2026-09-30: "refusal message truncated 500 characters remedy sentence cut CLIENT_MESSAGE_MAX cross-class field comparison INVALID_FILTER". 5 hits, all closed: #20039, #19879, #15661, #8197, #5423. #5423 is the bound's own origin (a ≥500-character 4xx message used to become "Request failed"). None covers this message's remedy.Dedupe words:
refusal remedy truncated 500·crossFieldClassError message length·CLIENT_MESSAGE_MAX cuts prescription·explain cross-class refusal remedy cutGenerated by Claude Code