Found while repairing chart-config-missing's over-reach for #14436 (PR #15461). Out of scope there — that card names one rule id, and this is a different id in the same file — but it is the same measurement, applied one rule over.
The claim, and what the pinned renderer does
chart-field-unknown (packages/lint/src/validate-widget-bindings.ts) is severity error — build-blocking, and gating on the sys_metadata publish path — on three chartConfig keys: chartConfig.xAxis.field, chartConfig.yAxis[].field and chartConfig.series[].name. Its messages say the query result "will not contain" the named column.
Read at the @object-ui revision this repo pins (.objectui-sha = 00d3f09c500c4a45b5f27aca8af80349412faaf1), the renderer never reaches that consequence, because it never reads those keys as bindings. packages/plugin-dashboard/src/__tests__/DatasetWidget.chartConfig.test.tsx pins it by name:
:179 "ignores an authored axis field and keeps the derived axis binding"
:192 "ignores an authored series and keeps one derived series per measure"
and mergeAuthoredPresentation strips ChartAxis.field / ChartSeries.name before the config reaches the chart. An authored xAxis.field: 'not_a_column' costs the widget nothing: the axis stays bound to dimensions[0].
Why it may still be right to report — and why the tier is the question
This is not the same defect as #14436. There, the rule fired on metadata that is completely valid. Here the metadata really is wrong: the author wrote a binding, believes it is in force, and it is not. Reporting it is defensible. What is not obviously defensible is the pair of severity and stated consequence:
- Consequence. "the query result will not contain it" describes a data failure. The actual failure is that the key is ignored — which is precisely the class
widget-legacy-analytics-shape in the same file reports at warning tier ("the dashboard renderer ignores them ... a silent no-op").
- Severity. An
error blocks a build and a Studio publish for a key that changes nothing at runtime. Against a widget whose selection is otherwise valid, the page renders correctly either way.
There is a real argument for keeping error: an author who wrote a binding that is silently refused has a misunderstanding worth stopping on, and the family's stated principle is that a silent-in-the-flattering-direction failure gates rather than advises. There is an equally real argument that this is widget-legacy-analytics-shape's class wearing the wrong tier.
What to decide
- Keep
error, and correct the message to name the real consequence (the binding is refused by the renderer, not dropped by the query).
- Demote to
warning and align the wording with widget-legacy-analytics-shape, on the grounds that an ignored presentation key is not a broken page.
Either way the message should stop describing a query that never runs. Recommendation is (1) plus a reworded message — the finding is worth keeping loud, and demoting it would make an authored-but-refused binding suppressible, which is how it became invisible in the first place. But the tier is a product judgement, not a measurement, which is why this is a card rather than a patch.
Filed unassigned and unlabeled for triage — not started, no branch.
Generated by Claude Code
Found while repairing
chart-config-missing's over-reach for #14436 (PR #15461). Out of scope there — that card names one rule id, and this is a different id in the same file — but it is the same measurement, applied one rule over.The claim, and what the pinned renderer does
chart-field-unknown(packages/lint/src/validate-widget-bindings.ts) is severityerror— build-blocking, and gating on thesys_metadatapublish path — on threechartConfigkeys:chartConfig.xAxis.field,chartConfig.yAxis[].fieldandchartConfig.series[].name. Its messages say the query result "will not contain" the named column.Read at the
@object-uirevision this repo pins (.objectui-sha=00d3f09c500c4a45b5f27aca8af80349412faaf1), the renderer never reaches that consequence, because it never reads those keys as bindings.packages/plugin-dashboard/src/__tests__/DatasetWidget.chartConfig.test.tsxpins it by name::179"ignores an authored axisfieldand keeps the derived axis binding":192"ignores an authored series and keeps one derived series per measure"and
mergeAuthoredPresentationstripsChartAxis.field/ChartSeries.namebefore the config reaches the chart. An authoredxAxis.field: 'not_a_column'costs the widget nothing: the axis stays bound todimensions[0].Why it may still be right to report — and why the tier is the question
This is not the same defect as #14436. There, the rule fired on metadata that is completely valid. Here the metadata really is wrong: the author wrote a binding, believes it is in force, and it is not. Reporting it is defensible. What is not obviously defensible is the pair of severity and stated consequence:
widget-legacy-analytics-shapein the same file reports at warning tier ("the dashboard renderer ignores them ... a silent no-op").errorblocks a build and a Studio publish for a key that changes nothing at runtime. Against a widget whose selection is otherwise valid, the page renders correctly either way.There is a real argument for keeping
error: an author who wrote a binding that is silently refused has a misunderstanding worth stopping on, and the family's stated principle is that a silent-in-the-flattering-direction failure gates rather than advises. There is an equally real argument that this iswidget-legacy-analytics-shape's class wearing the wrong tier.What to decide
error, and correct the message to name the real consequence (the binding is refused by the renderer, not dropped by the query).warningand align the wording withwidget-legacy-analytics-shape, on the grounds that an ignored presentation key is not a broken page.Either way the message should stop describing a query that never runs. Recommendation is (1) plus a reworded message — the finding is worth keeping loud, and demoting it would make an authored-but-refused binding suppressible, which is how it became invisible in the first place. But the tier is a product judgement, not a measurement, which is why this is a card rather than a patch.
Filed unassigned and unlabeled for triage — not started, no branch.
Generated by Claude Code