Skip to content

fix(charts): prevent TypeError crash when streaming nullish data#651

Open
serhiizghama wants to merge 2 commits into
thesysdev:mainfrom
serhiizghama:fix/charts-guard-nullish-data-streaming
Open

fix(charts): prevent TypeError crash when streaming nullish data#651
serhiizghama wants to merge 2 commits into
thesysdev:mainfrom
serhiizghama:fix/charts-guard-nullish-data-streaming

Conversation

@serhiizghama

Copy link
Copy Markdown

Problem

Closes #355.

Every public chart component (BarChart, BarChartCondensed, LineChart, AreaChart, PieChart, RadarChart, ScatterChart, …) reads its data prop directly — getDataKeys(data, …), data.length, [...data].sort() — assuming data is always an array.

While generative UI is streaming, data can momentarily be null/undefined before the full payload has been parsed. Passing that into the chart internals throws:

TypeError: Cannot read properties of null (reading '0')   // getDataKeys
TypeError: Cannot read properties of null (reading 'length')
TypeError: data is not iterable                            // [...data]

This crashes the whole render mid-stream.

Solution

Add a small shared helper normalizeChartData() in Charts/utils/dataUtils.ts that coerces data to an array, and call it once at the top of each chart component so the rest of the component always works with a real array (an empty chart instead of a crash).

Two details that make it safe:

  • Stable empty reference — when data is nullish it falls back to a single shared EMPTY_CHART_DATA constant, so normalization never creates a new [] on every render (which would change identity and defeat the existing useMemo/React.memo optimizations). When data is a valid array it is returned by reference, unchanged.
  • getDataKeys() is also made null-safe (data?.[0]) as defense-in-depth, since it is the shared first access point.

The genui-lib schema layer already guards its own path via hasAllProps/buildChartData; this PR hardens the public exported chart components themselves, which are part of the package surface and can be rendered directly by consumers (and during streaming).

This matches the approach agreed on in the issue thread (Array.isArray(data) ? data : [], applied consistently across all chart types).

Testing

  • pnpm --filter @openuidev/react-ui typecheck — passes
  • pnpm --filter @openuidev/react-ui ci (lint:check + format:check) — passes
  • Verified normalizeChartData(null)/(undefined) return the same stable empty array, valid arrays pass through by reference, and getDataKeys(null) returns [] instead of throwing.

Add normalizeChartData() to coerce a chart's data prop to a stable
array, and make getDataKeys() null-safe. During streaming, data can be
null/undefined before the full payload arrives, which previously threw
inside the chart internals.
Every public chart component read the data prop directly (getDataKeys,
data.length, [...data]) assuming it was always an array. While generative
UI streams, data can momentarily be null/undefined, crashing the chart
with 'Cannot read properties of null'. Normalize data at each component
entry so charts render an empty state instead of throwing.
@vishxrad

Copy link
Copy Markdown
Contributor

Thanks for the PR. We’re going to address this at the genui-lib streaming/parser layer rather than in each chart component. Please keep this PR open for now while we implement and verify that approach. Once the replacement is confirmed, we’ll close this PR as superseded. We’ll track the work in #355.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Charts component crashes with TypeError during streaming: null data passed to Recharts

2 participants