Skip to content

fix(chart): defer sankey render until container has a non-zero size#83

Open
TomK wants to merge 1 commit into
masterfrom
fix/sankey-zero-size-container
Open

fix(chart): defer sankey render until container has a non-zero size#83
TomK wants to merge 1 commit into
masterfrom
fix/sankey-zero-size-container

Conversation

@TomK

@TomK TomK commented Jun 4, 2026

Copy link
Copy Markdown
Member

Problem

A zn-chart type="sankey" crashes on draw with:

TypeError: Cannot read properties of null (reading '0')
    at ... r._updateViewCoordSys ... r.render

The crash is not caused by the chart data (orphan nodes, link values, etc.). The trigger is a zero-width or zero-height container at render time. ECharts' bar/line layouts tolerate a zero-size container; the sankey layout does not — it builds a degenerate coordinate system and reads null[0] in _updateViewCoordSys, matching the reported stack trace.

zn-chart forces the host height (default 300px) but takes its width from layout. So when a sankey chart initialises inside a hidden tab or a flex/grid cell that has not been laid out yet, width is 0 and it crashes.

Fix

Defer setOption until the chart container reports a non-zero size:

  • New renderChart() guard — if width or height is 0, mark pendingRender and skip; otherwise apply the option.
  • The existing ResizeController triggers the deferred render once the container gains a size (e.g. a hidden tab becomes visible).
  • All full-option setOption call sites (init, live updates, attribute changes) routed through the guard.

No behaviour change for charts that already have a sized container.

Test plan

  • Reproduced the exact error in a real headless browser (Playwright + echarts canvas): a sankey chart set into a width:0 / height:300px container threw Cannot read properties of null (reading '0'); bar and line charts in the same container rendered fine.
  • Verified the fixed control flow in the same harness: initialising at width:0 defers without throwing (pendingRender=true), and after the container is given a width the ResizeObserver fires and the chart renders (series.length > 0) with no page errors.
  • Added a regression test in chart.test.ts (does not crash when a sankey chart starts in a zero-width container).
  • tsc --noEmit passes; no new lint errors introduced.

Notes for reviewer

  • The repo's component test suite imports the built dist/zn.min.js, so the new regression test only exercises this fix after a dist rebuild. I did not rebuild dist in this PR because the production build currently fails on an unrelated, pre-existing error (markdown-editor.component.ts(282,53): Property 'description' does not exist on type 'ZnMarkdownEditor'). That should be addressed separately before the next bundle is cut.

🤖 Generated with Claude Code

ECharts' sankey layout crashes with "Cannot read properties of null
(reading '0')" when asked to render into a zero-width or zero-height
container (e.g. a chart created inside a hidden tab or a flex/grid cell
that has not been laid out yet). bar/line charts tolerate this; sankey
does not.

zn-chart forces the host height but takes its width from layout, so a
sankey chart initialised before its container has a width crashes.

Defer setOption until the chart container reports a non-zero size, and
let the existing ResizeController trigger the deferred render once the
container becomes visible. Route all full-option setOption call sites
through the guard.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant