# ECharts Chart Not Showing — Blank Container, Zero Height and Missing-Import Fixes

Canonical: https://commareports.com/fix/echarts-chart-not-showing
Published: 2026-10-24

> Your Apache ECharts chart renders nothing. Match the symptom — echarts is not defined, Initialize failed: invalid dom, Can't get DOM width or height, is used but not imported, Map not exists — to its fix, including hidden tabs, setOption merging and pyecharts HTML.

# The ECharts chart isn't showing

ECharts fails in two ways: loudly, with an error in the console, or
silently, with a perfectly empty `<div>`. The silent case is the common
one, and it is almost always about size. Open DevTools (F12), check the
**Console**, then inspect the container in **Elements** — if ECharts ran,
there is a `<canvas>` (or `<svg>`) inside it, and its width and height
tell you most of the story.

One thing to know first: **the minified build hides the hints.**
`echarts.min.js` strips ECharts' development warnings, including the one
about zero-size containers. Swap in `echarts.js` while you debug.

## Match the symptom

| What you see                                                | Cause                                              |
| ----------------------------------------------------------- | -------------------------------------------------- |
| `Uncaught ReferenceError: echarts is not defined`           | The library never loaded                           |
| `Error: Initialize failed: invalid dom.`                    | `echarts.init()` got `null`                        |
| Empty `<div>`, no error (minified build)                    | Container is 0px tall                              |
| `Can't get DOM width or height…` (unminified build)         | Container is 0px tall                              |
| Chart blank until the window is resized                     | Initialised while hidden (`display: none`)         |
| `… is used but not imported`                                | `echarts/core` without `echarts.use([...])`        |
| `Map … not exists. The GeoJSON of the map must be provided` | Map not registered                                 |
| `There is a chart instance already initialized on the dom.` | `init()` called twice on one element               |
| Old series still drawn after `setOption`                    | `setOption` merges by default                      |
| Axes drawn, no bars or lines                                | Data arrived after `setOption`, or wrong axis type |
| `Access to fetch at 'file:///…' … blocked by CORS policy`   | Loading data or GeoJSON from a local file          |

## The library didn't load

`echarts` exists only after its `<script>` has run. Load it above your
code and pin the major version you built against:

```html
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
```

If the Network tab shows that request failing, the CDN is blocked — a
corporate proxy, an offline laptop, or a viewer whose Content-Security-Policy
refuses third-party scripts. A local `echarts.min.js` works for you and
404s for everyone you send just the `.html` to;
[the same trap as lost CSS](/html-report-broken-css).

With a bundler, `import * as echarts from "echarts"` is the full build.
`import echarts from "echarts"` is `undefined` in ECharts 5 — there is no
default export.

## The container is 0px tall

```html
<div id="chart"></div>
<!-- height: auto, no content → 0px -->
```

ECharts reads `clientWidth` and `clientHeight` once, at `init()`. A `div`
with no explicit height has none, so the canvas is created at 0 pixels
and nothing is visible. Give it a size:

```html
<div id="chart" style="width: 100%; height: 420px"></div>
```

`height: 100%` only works if every ancestor up to one with a fixed height
also has a height. Inside a flex column, use `flex: 1; min-height: 0` on
the container and make sure the flex parent itself is sized.

## `Initialize failed: invalid dom`

`document.getElementById("chart")` returned `null` — the script ran in
`<head>` before the `div` existed, or the id doesn't match. Put the
script after the element, add `defer`, or wrap the code:

```js
document.addEventListener("DOMContentLoaded", () => {
  const chart = echarts.init(document.getElementById("chart"));
  chart.setOption(option);
});
```

## Blank in a tab, modal or accordion

A container that is `display: none` at `init()` measures 0×0 — same bug,
different cause. When the panel opens, tell the chart to measure again:

```js
tabButton.addEventListener("click", () => {
  showPanel();
  chart.resize();
});
```

Charts that should follow their container — sidebars collapsing, split
panes, window resizing — want a `ResizeObserver`:

```js
new ResizeObserver(() => chart.resize()).observe(chart.getDom());
```

In React or Vue, also call `chart.dispose()` on unmount. Re-running
`echarts.init()` on an element that already has a chart logs
_"There is a chart instance already initialized on the dom"_ and reuses
the old instance; use `echarts.getInstanceByDom(el) ?? echarts.init(el)`.

## `… is used but not imported`

The `echarts/core` entry point is tree-shakeable: it ships nothing until
you register it. Every series type, every component the option mentions
(`grid`, `tooltip`, `legend`, `dataZoom`, `title`…) and one renderer have
to be passed to `echarts.use`:

```js
import * as echarts from "echarts/core";
import { BarChart, LineChart } from "echarts/charts";
import {
  GridComponent,
  TooltipComponent,
  LegendComponent,
  DatasetComponent,
} from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";

echarts.use([
  BarChart,
  LineChart,
  GridComponent,
  TooltipComponent,
  LegendComponent,
  DatasetComponent,
  CanvasRenderer,
]);
```

A missing component is quieter than a missing series: forget
`TooltipComponent` and the chart draws, it just never shows a tooltip.

## The map is empty

ECharts 5 removed the bundled world and country maps. A `geo` component
or `map` series that names `"world"` draws nothing until you register the
GeoJSON yourself:

```js
const geoJson = await fetch("/maps/world.json").then((r) => r.json());
echarts.registerMap("world", geoJson);
chart.setOption({ series: [{ type: "map", map: "world", data }] });
```

The name in `registerMap` and the `map:` option must match exactly, and
the region names in your `data` must match the `name` properties in the
GeoJSON — `"United States"` and `"United States of America"` are
different regions.

## `setOption` kept the old data

`setOption` merges into the existing option. Removing a series, or
switching from four series to two, leaves the extras on screen. Replace
instead of merge:

```js
chart.setOption(option, { notMerge: true });
// or only replace the series array:
chart.setOption(option, { replaceMerge: ["series"] });
```

If data comes from `fetch`, set the option after it resolves — or set the
axes first, call `chart.showLoading()`, and `hideLoading()` plus
`setOption({ series: [...] })` when the data lands. And check the axis
type: a `category` axis needs labels (`xAxis.data` or a `dataset`), while
numeric x values belong on a `value` or `time` axis.

## Data or GeoJSON from a local file

Opened as `file://`, the page has an opaque origin and the browser blocks
`fetch()` of neighbouring files — the
[CORS error from origin 'null'](/fix/cors-error-file-origin-null). Serve
the folder over HTTP while developing (`python3 -m http.server`) and
inline the data into the page for anything you send.

## pyecharts HTML is blank

`Bar().render("chart.html")` writes a page whose `<script>` points at the
pyecharts assets host on the web. No network, a proxy, or a strict CSP,
and the file opens empty. Point it at a CDN you know is reachable before
rendering:

```python
from pyecharts.globals import CurrentConfig

CurrentConfig.ONLINE_HOST = "https://cdn.jsdelivr.net/npm/echarts@5/dist/"
```

Or copy `echarts.min.js` next to the HTML and set `ONLINE_HOST` to that
folder — then send the folder, not just the file.

## Or skip the script for this chart

If the chart only has to be _read_ — a bar, line or pie in a report or a
PR comment — it may not need a charting runtime at all. Paste the numbers
into [CSV to chart](/tools/csv-to-chart) or
[JSON to chart](/tools/json-to-chart) and get a static SVG that can't
fail to load.

## Sharing an ECharts chart that works

When it renders, send a link instead of the file. Published to Comma, the
page runs in a sandboxed iframe (`allow-scripts`, no `allow-same-origin`),
so tooltips, legend toggles and `dataZoom` keep working, and reviewers
comment on the exact bar or data point they mean. Two caveats: a published
report can't `fetch()` sibling files, so inline the data and GeoJSON; and
[vendor the library](/share-echarts-html) if your readers sit behind a
proxy that blocks CDNs.

**[Publish an ECharts report →](https://commareports.com/)**

### Related

- [Share an ECharts HTML file](/share-echarts-html)
- [Chart.js chart not showing](/fix/chartjs-chart-not-showing)
- [D3 chart not showing](/fix/d3-chart-not-showing)
- [Plotly chart missing from the exported HTML](/fix/plotly-chart-not-showing-in-html)
- [CORS error from origin 'null'](/fix/cors-error-file-origin-null)
- [CSV to chart](/tools/csv-to-chart) · [JSON to chart](/tools/json-to-chart)
