chartjs/Chart.js · error · Error
class does not have id: ${item}
Error message
class does not have id: ${item} What it means
TypedRegistry.register(item) requires item.id to be a truthy string; without it the registry cannot scope defaults (scope + '.' + id) or store the component. The error stringifies the offending item so you can see what was passed. It is thrown when Chart.register(...) (or auto-registration) receives a class/object lacking a static `id` property.
Source
Thrown at src/core/core.typedRegistry.js:38
/**
* @param {IChartComponent} item
* @returns {string} The scope where items defaults were registered to.
*/
register(item) {
const proto = Object.getPrototypeOf(item);
let parentScope;
if (isIChartComponent(proto)) {
// Make sure the parent is registered and note the scope where its defaults are.
parentScope = this.register(proto);
}
const items = this.items;
const id = item.id;
const scope = this.scope + '.' + id;
if (!id) {
throw new Error('class does not have id: ' + item);
}
if (id in items) {
// already registered
return scope;
}
items[id] = item;
registerDefaults(item, scope, parentScope);
if (this.override) {
defaults.override(item.id, item.overrides);
}
return scope;
}
/**
* @param {string} idView on GitHub (pinned to cb02e1d207)
Solutions
- Add a static id to the component class: `class MyScale extends Scale { static id = 'myScale'; static defaults = {}; }`.
- Confirm every argument passed to Chart.register(...) is a class/object with a string `id`.
- Guard dynamic imports: only register when the imported value is defined and has an id.
- If registering an object form, ensure it has an `id` key (e.g. Chart.register({ id: 'myPlugin', ... })).
Example fix
// before
class MyPlugin {
afterDraw(chart) { /* ... */ }
}
Chart.register(MyPlugin); // no static id -> throws
// after
class MyPlugin {
static id = 'myPlugin';
afterDraw(chart) { /* ... */ }
}
Chart.register(MyPlugin); Defensive patterns
Strategy: validation
Validate before calling
// Validate that every item passed to Chart.register has an id.
import { Chart } from 'chart.js';
function registerSafely(...items) {
for (const item of items) {
if (!item || typeof item !== 'function' && typeof item !== 'object') {
throw new Error('Chart.register received a non-component: ' + String(item));
}
if (!item.id || typeof item.id !== 'string') {
throw new Error('Component missing static id: ' + (item.name || String(item)));
}
}
Chart.register(...items);
} Type guard
// Type guard ensuring a component class/object has an id.
function isRegistrableComponent(c) {
return Boolean(c) && (typeof c === 'function' || typeof c === 'object') && typeof c.id === 'string' && c.id.length > 0;
} Prevention
- Always declare `static id = '...';` on custom Chart.js components.
- Wrap Chart.register in a project helper that checks for an id.
- Unit-test custom plugins/scales by constructing and registering them in isolation.
- Beware bundlers that drop static class fields; target ES2015+ for static field semantics.
When it happens
Trigger: Calling Chart.register(MyClass) where MyClass has no static `id`; registering a plain object instead of a component class with an id; a custom plugin/scale/element/controller defined without an `id` static field; passing undefined/null into register() (e.g. a failed dynamic import).
Common situations: Authoring a custom Chart.js component and forgetting `static id = 'myThing'`; refactoring that renames/removes the id; bundler tree-shaking removing the static id assignment; copy-pasting a plugin snippet that omitted the id.
Related errors
- "${id}" is not a registered ${type}.
- Unsupported decimation algorithm '${options.algorithm}'
- This method is not implemented: Check that a complete date a
- Cannot determine type of '${id}' axis. Please provide 'axis'
- Recursion detected: ${Array.from(_stack).join('->')}->${prop
AI-assisted analysis of chartjs/Chart.js@cb02e1d207 (2026-08-12).
Data as JSON: /api/errors/9f922c327e1999c8.
Report an issue: GitHub.