Surfaced by the objectui#8168 dev seat while enumerating every producer that reaches ObjectChart (the stop condition on that card's dispatch). ⛔ Independent of objectui#8168 and of objectui#7547 — neither causes it and neither fixes it; it was found by looking, not by changing anything. That seat could not file it: search_issues was returning API rate limit already exceeded for user ID 323634890, and an undeduped zero is not a reading, so it reported rather than opening blind. Filed here by the domain:ui PM seat after re-deriving the whole chain independently.
The defect
A dashboard chart widget bound to an object, aggregating { function: 'count', groupBy: 'status' } with no field, renders an empty chart. No error, no empty state — a chart frame with nothing in it.
The chain, measured end to end on origin/main 0fa7a9c83
Two independent copies, same shape:
packages/plugin-dashboard/src/DashboardGridLayout.tsx:227 const yField = options.yField || 'value';
packages/plugin-dashboard/src/DashboardGridLayout.tsx:239 const effectiveYField = effectiveAggregate?.field || yField;
packages/plugin-dashboard/src/DashboardGridLayout.tsx:246 series: [{ dataKey: effectiveYField }],
packages/plugin-dashboard/src/DashboardRenderer.tsx:607 const yField = options.yField || 'value';
packages/plugin-dashboard/src/DashboardRenderer.tsx:618 const effectiveYField = effectiveAggregate?.field || yField;
⇒ for { function: 'count', groupBy: 'status' } the aggregate carries no field, so effectiveAggregate?.field is undefined and effectiveYField falls back to 'value'.
Meanwhile the rows are projected under a different key:
packages/plugin-charts/src/ObjectChart.tsx:37-38
export function aggregateValueKey(aggregate: { field?: string; function?: string }): string {
return aggregate.field || aggregate.function || 'count';
}
⇒ for the same aggregate this returns 'count'. That is not an inference — it is already pinned by a test on main:
packages/plugin-charts/src/ObjectChart.aggregateResultColumns.test.ts:34
it('is the literal "count" when a count names no field', () => {
expect(aggregateValueKey({ function: 'count' })).toBe('count');
});
⇒ the series asks for dataKey: 'value'; every row carries 'count'. Nothing matches, nothing plots.
⭐ Corroboration that the tree already half-knows this. DashboardRenderer.tsx:320 reads:
const isSynthetic = !yField || yField === 'value' || yField === 'count';
The label path explicitly handles the 'value' / 'count' duality. The dataKey path does not consult it. So the same duality is understood in one place and dropped in the other.
⚠️ A second inconsistency, named but not claimed as part of this defect: DashboardGridLayout.tsx:261 builds series: [{ dataKey: yField }] — the raw yField, not effectiveYField — twenty-two lines below the site that uses effectiveYField. Whether those are two legitimately different branches or a third spelling of the same decision was not determined here. Whoever takes this should settle it rather than patching only :239/:618.
⚠️ Confidence — stated rather than implied
Source-derived, NOT render-measured. Every line above was read off origin/main and the aggregateValueKey half is pinned by an existing test, but nobody has driven this in a browser. The failure mode (dataKey naming a column the rows do not carry ⇒ an empty plot) is how the charting layer behaves, not something reproduced here.
⇒ Whoever picks this up reproduces it first. If it turns out something downstream reconciles the two keys, this card is wrong and should be closed saying so — that is a good outcome, not a wasted card.
Why it is worth a card
The failure is silent and credible: an empty chart looks like "no data yet", which is exactly what an author with a genuinely empty object would also see. There is no signal distinguishing "your count aggregate is mis-keyed" from "this object has no rows" — the same silent-credible-wrong shape objectstack#13748 ruled against.
count with no field is also the normal way to author "how many records per status", which is the most common dashboard chart there is.
Dedup
⚠️ Not deduped — declared, not hidden. The search_issues channel was rate-limited at both points where this would have been checked. An uncontrolled zero carries no information, so no dedup claim is made. Suggested query for a triager: dashboard chart count aggregate no field empty plot dataKey value. Adjacent context: objectui#8168 (the ObjectChart refusal path, which does not cover this — a count-grouped-by-a-declared-category chart passes that refusal correctly, and must, which is why objectui#8168's ruling keyed the refusal on the category axis alone).
Refs: objectui#8168 · objectui#7547 · objectstack#13748.
Surfaced by the objectui#8168 dev seat while enumerating every producer that reaches
ObjectChart(the stop condition on that card's dispatch). ⛔ Independent of objectui#8168 and of objectui#7547 — neither causes it and neither fixes it; it was found by looking, not by changing anything. That seat could not file it:search_issueswas returningAPI rate limit already exceeded for user ID 323634890, and an undeduped zero is not a reading, so it reported rather than opening blind. Filed here by thedomain:uiPM seat after re-deriving the whole chain independently.The defect
A dashboard chart widget bound to an object, aggregating
{ function: 'count', groupBy: 'status' }with nofield, renders an empty chart. No error, no empty state — a chart frame with nothing in it.The chain, measured end to end on
origin/main0fa7a9c83Two independent copies, same shape:
⇒ for
{ function: 'count', groupBy: 'status' }the aggregate carries nofield, soeffectiveAggregate?.fieldisundefinedandeffectiveYFieldfalls back to'value'.Meanwhile the rows are projected under a different key:
⇒ for the same aggregate this returns
'count'. That is not an inference — it is already pinned by a test on main:⇒ the series asks for
dataKey: 'value'; every row carries'count'. Nothing matches, nothing plots.⭐ Corroboration that the tree already half-knows this.
DashboardRenderer.tsx:320reads:The label path explicitly handles the
'value'/'count'duality. The dataKey path does not consult it. So the same duality is understood in one place and dropped in the other.DashboardGridLayout.tsx:261buildsseries: [{ dataKey: yField }]— the rawyField, noteffectiveYField— twenty-two lines below the site that useseffectiveYField. Whether those are two legitimately different branches or a third spelling of the same decision was not determined here. Whoever takes this should settle it rather than patching only:239/:618.Source-derived, NOT render-measured. Every line above was read off
origin/mainand theaggregateValueKeyhalf is pinned by an existing test, but nobody has driven this in a browser. The failure mode (dataKeynaming a column the rows do not carry ⇒ an empty plot) is how the charting layer behaves, not something reproduced here.⇒ Whoever picks this up reproduces it first. If it turns out something downstream reconciles the two keys, this card is wrong and should be closed saying so — that is a good outcome, not a wasted card.
Why it is worth a card
The failure is silent and credible: an empty chart looks like "no data yet", which is exactly what an author with a genuinely empty object would also see. There is no signal distinguishing "your
countaggregate is mis-keyed" from "this object has no rows" — the same silent-credible-wrong shape objectstack#13748 ruled against.countwith nofieldis also the normal way to author "how many records per status", which is the most common dashboard chart there is.Dedup
search_issueschannel was rate-limited at both points where this would have been checked. An uncontrolled zero carries no information, so no dedup claim is made. Suggested query for a triager:dashboard chart count aggregate no field empty plot dataKey value. Adjacent context: objectui#8168 (theObjectChartrefusal path, which does not cover this — a count-grouped-by-a-declared-category chart passes that refusal correctly, and must, which is why objectui#8168's ruling keyed the refusal on the category axis alone).Refs: objectui#8168 · objectui#7547 · objectstack#13748.