Found while implementing objectui#7194 (PR #7400). Not fixed there — a different mechanism and outside that card's scope.
What was measured
Rendered through the real SDUI path (SchemaRenderer from @object-ui/react, with @object-ui/plugin-charts imported so its registrations run, in vitest with the real Recharts and a 480x320 container), each schema carrying xAxisKey: 'xm', series: [{ dataKey: 'ym' }, { dataKey: 'zm' }] and two numeric rows:
schema type | .recharts-scatter | .recharts-bar | .recharts-pie | data-chart-error |
|---|
scatter-chart | 0 | 2 | 0 | none |
plugin-charts:scatter-chart | 0 | 2 | 0 | none |
pie-chart | 0 | 2 | 0 | none |
plugin-charts:chart with chartType: 'scatter' (control) | 0 | 0 | 0 | scatter-multi-series (PR #7400's refusal, i.e. the scatter arm was reached) |
Three chart-type registrations rendered a two-series bar chart. Only the generic chart type with an explicit chartType reached the family it names.
Why
packages/plugin-charts/src/index.tsx registers pie-chart, donut-chart, radar-chart, scatter-chart (and siblings) as ChartRenderer with defaultProps: { chartType: FAMILY }. Nothing on the SDUI path reads that option: git grep defaultProps packages/react/src packages/core/src finds one consumer, WidgetRegistry.ts (manifest defaultProps for widgets), and none in SchemaRenderer. ChartRenderer then computes chartType: schema.chartType ?? spec.chartType, both undefined for these schemas, and AdvancedChartImpl defaults to 'bar'.
chart:bar is registered through a separate ChartBarRenderer wrapper that sets the family itself, which is why that one works — and why the fix is a decision (apply defaultProps in the renderer for every registration, or give each chart-type registration its own wrapper like chart:bar) rather than a one-liner.
Why it matters
Same class as objectui#7194: valid data, a confidently wrong picture, no refusal that can fire. An author who writes type: 'pie-chart' gets a bar chart with no diagnostic. The documented chart-type registrations (content/docs/plugins/plugin-charts.mdx lists them) are therefore all one family.
It also blinds a sweep: packages/app-shell/src/__tests__/widget-dom-leak-sweep.test.tsx renders plugin-charts:pie-chart, donut-chart, radar-chart and scatter-chart entries and waits on [data-slot="chart"] — all four pass as bar charts, so the pie / donut / radar / scatter renderers are not actually swept there. (This is how the finding surfaced: PR #7400's refusal should have broken that sweep's two-series scatter-chart entry and did not.)
Not measured
- Whether any published example or tenant metadata uses the
FAMILY-chart types (in-repo: packages/plugin-charts/examples/chart-examples.ts uses type: 'pie-chart' — it would draw a bar). - Whether
WidgetRegistry's manifest defaultProps path is affected (it has its own consumer; likely not).
Refs: objectui#7194 · PR #7400 (the control row above).
Generated by Claude Code
Found while implementing objectui#7194 (PR #7400). Not fixed there — a different mechanism and outside that card's scope.
What was measured
Rendered through the real SDUI path (
SchemaRendererfrom@object-ui/react, with@object-ui/plugin-chartsimported so its registrations run, in vitest with the real Recharts and a 480x320 container), each schema carryingxAxisKey: 'xm',series: [{ dataKey: 'ym' }, { dataKey: 'zm' }]and two numeric rows:type.recharts-scatter.recharts-bar.recharts-piedata-chart-errorscatter-chartplugin-charts:scatter-chartpie-chartplugin-charts:chartwithchartType: 'scatter'(control)scatter-multi-series(PR #7400's refusal, i.e. the scatter arm was reached)Three chart-type registrations rendered a two-series bar chart. Only the generic
charttype with an explicitchartTypereached the family it names.Why
packages/plugin-charts/src/index.tsxregisterspie-chart,donut-chart,radar-chart,scatter-chart(and siblings) asChartRendererwithdefaultProps: { chartType: FAMILY }. Nothing on the SDUI path reads that option:git grep defaultProps packages/react/src packages/core/srcfinds one consumer,WidgetRegistry.ts(manifest defaultProps for widgets), and none inSchemaRenderer.ChartRendererthen computeschartType: schema.chartType ?? spec.chartType, both undefined for these schemas, andAdvancedChartImpldefaults to'bar'.chart:baris registered through a separateChartBarRendererwrapper that sets the family itself, which is why that one works — and why the fix is a decision (applydefaultPropsin the renderer for every registration, or give each chart-type registration its own wrapper likechart:bar) rather than a one-liner.Why it matters
Same class as objectui#7194: valid data, a confidently wrong picture, no refusal that can fire. An author who writes
type: 'pie-chart'gets a bar chart with no diagnostic. The documented chart-type registrations (content/docs/plugins/plugin-charts.mdxlists them) are therefore all one family.It also blinds a sweep:
packages/app-shell/src/__tests__/widget-dom-leak-sweep.test.tsxrendersplugin-charts:pie-chart,donut-chart,radar-chartandscatter-chartentries and waits on[data-slot="chart"]— all four pass as bar charts, so the pie / donut / radar / scatter renderers are not actually swept there. (This is how the finding surfaced: PR #7400's refusal should have broken that sweep's two-seriesscatter-chartentry and did not.)Not measured
FAMILY-charttypes (in-repo:packages/plugin-charts/examples/chart-examples.tsusestype: 'pie-chart'— it would draw a bar).WidgetRegistry's manifestdefaultPropspath is affected (it has its own consumer; likely not).Refs: objectui#7194 · PR #7400 (the control row above).
Generated by Claude Code