The Chart.js chart isn't showing
The page loads. There's a gap — or nothing at all — where the chart should be. Chart.js almost never fails loudly on the page itself, but it nearly always says something in the console. Open DevTools (F12 → Console) and match the message.
Match the console message
| Console says | Cause |
|---|---|
Failed to create chart: can't acquire context from the given item |
The canvas wasn't found when the script ran |
Uncaught ReferenceError: Chart is not defined |
The library never loaded |
"bar" is not a registered controller. |
Chart.js 3+ imported without registering types |
Canvas is already in use. Chart with ID '0' must be destroyed… |
A second chart on the same canvas |
| Nothing, chart area is empty or flat | Zero-size container, or v2 options in v3/v4 |
Access to fetch at 'file:///…' … has been blocked by CORS policy |
Data loaded with fetch() from a local file |
"Can't acquire context from the given item"
new Chart(el, config) got null. The script ran before the browser
parsed the <canvas>, or the id doesn't match.
<canvas id="sales"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4"></script>
<script>
// After the canvas, so getElementById finds it.
new Chart(document.getElementById("sales"), { type: "bar", data: { … } });
</script>
If the script has to live in <head>, give it defer or wrap the code in
document.addEventListener("DOMContentLoaded", …).
"Chart is not defined"
The global Chart only exists once the library's <script> has run.
Check, in order:
- The tag is above your code. Scripts run top to bottom.
- The request succeeded. The Network tab shows a failed or blocked
request for
chart.umd.jsorchart.min.jswhen you're offline, behind a proxy that blocks the CDN, or inside a viewer whose Content-Security-Policy refuses it — CSP versus mixed content. - A local copy travelled with the page.
<script src="chart.min.js">works on your machine and 404s once only the.htmlfile is sent — the same trap as a report that lost its CSS.
"is not a registered controller"
Chart.js 3 made the npm package tree-shakeable. With a bundler,
import { Chart } from "chart.js" registers no chart types, scales or
elements.
import Chart from "chart.js/auto"; // everything registered
Or register exactly what you use: Chart.register(BarController, BarElement, CategoryScale, LinearScale, Tooltip, Legend). A missing scale
produces the sibling error, "category" is not a registered scale.
"Canvas is already in use"
You built a new chart on a canvas that still holds the old one — usually in a function that re-runs when a filter changes. Keep the instance:
let chart;
function render(data) {
if (chart) chart.destroy();
chart = new Chart(canvas, { type: "line", data });
}
Updating in place (chart.data = data; chart.update();) is cheaper and
keeps the animation smooth.
The silent failures
The chart has no height. Responsive charts size from their parent.
maintainAspectRatio: false tells the canvas to take the parent's
height — and a div with no explicit height has none. Give the wrapper a
real size and keep it for the chart alone:
<div style="position: relative; height: 320px">
<canvas id="sales"></canvas>
</div>
It was created while hidden. A chart built inside a display: none
tab, accordion or modal measures 0×0. Create it when the panel opens, or
call chart.resize() then.
Options from a Chart.js 2 tutorial. scales: { yAxes: [{ … }] } and
ticks: { beginAtZero: true } under yAxes are v2 syntax; v3 and v4
expect scales: { y: { beginAtZero: true } } and ignore the old shape
without an error. A CDN URL without a version — npm/chart.js — serves
the latest major, so a page that worked for years can change underneath
you. Pin it: npm/chart.js@4.
Blank in the PDF or screenshot. The capture fired mid-animation. Set
animation: false for anything printed, screenshotted or rendered
headless — see HTML to PDF and
HTML to image.
Data from a local JSON file. fetch("data.json") from a page opened
as file:// is blocked — CORS error from origin 'null'.
Inline the data in the page instead.
Or skip the script entirely
If the chart only has to be read — in a report, a pull request, an
email — it doesn't need a runtime library. Paste the numbers into
CSV to chart, or paste your Chart.js { labels, datasets } object straight into JSON to chart,
and get a static SVG bar, line or pie chart with no script, no CDN and
nothing to fail to load.
Sharing a chart that works
When the Chart.js page is right, send a link, not the file. Published to
Comma, scripts run in a sandboxed iframe (allow-scripts, no
allow-same-origin), so tooltips, legend toggles and animations work, and
the common CDNs load inside the frame. Reviewers select the number next to
the chart and comment on it in place instead of screenshotting it into
chat. One caveat: a published report can't fetch() sibling files, so
inline the data before you publish.