chartjs / chartjs/Chart.js

Possible plugin lifecycle regression in Chart.js 4.5.1 causing chartjs-plugin-datalabels to draw before internal labels are prepared

Open
#12,269 8 comments 0 reactions 0 assignees View on GitHub
type: bug
Dominant language
JavaScript
Stars
67.7k
Forks
11.9k
Avg merge
7h 39m
Merged PRs (30d)
5

Description

### Expected behavior

After upgrading from Chart.js 4.5.0 to 4.5.1, charts using chartjs-plugin-datalabels 2.2.0 can fail during render with:

TypeError: can't access property "length", labels is undefined

The stack points into chartjs-plugin-datalabels.js during its draw/layout step, where it expects a prepared labels array.

The same chart configuration works with Chart.js 4.5.0.

Suspicious Chart.js change
The likely related change is in src/core/core.plugins.js.

In 4.5.0, PluginService initialized _init as an empty array:

constructor() {
this._init = [];
}

In 4.5.1, _init is initialized as undefined, and plugin notifications return early if beforeInit has not populated it:

constructor() {
this._init = undefined;
}

notify(chart, hook, args, filter) {
if (hook === 'beforeInit') {
this._init = this._createDescriptors(chart, true);
this._notify(this._init, chart, 'install');
}

if (this._init === undefined) {
return;
}

...
}

Hypothesis
Some plugin lifecycle notifications may be skipped, so chartjs-plugin-datalabels does not receive the update hooks it uses to build its internal label layout, but later still reaches its draw hook. That leaves its internal labels undefined and causes the crash.

Environment
Chart.js: 4.5.1
Working version: 4.5.0
Plugin: chartjs-plugin-datalabels 2.2.0
Browser: include browser/version if known
Chart type: include the failing chart type, e.g. bar/pie

Minimal symptom
The failing plugin line is equivalent to:

for (i = 0, ilen = labels.length; i < ilen; ++i) {

where labels is unexpectedly undefined.

### Current behavior

Question
Was the PluginService._init === undefined guard intended to skip all plugin hooks before beforeInit, and could it cause inline/per-chart plugins such as ChartDataLabels to miss setup hooks but still receive draw hooks?

I tried to create a minimal CodePen using Chart.js 4.5.1 and chartjs-plugin-datalabels 2.2.0, but I have not been able to reproduce the error outside our REDCap page yet. The issue may depend on our page lifecycle or how the charts are created in that environment.

I understand this may not be actionable without a reproduction, but I wanted to ask whether the PluginService._init change in 4.5.1 could plausibly cause plugin setup hooks to be skipped while later draw hooks still run.

### Reproducible sample

https://www.chartjs.org/dist/master/chart.umd.min.js

### Optional extra steps/info to reproduce

_No response_

### Possible solution

_No response_

### Context

_No response_

### chart.js version

v4.5.1

### Browser name and version

_No response_

### Link to your project

_No response_

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in src/core/core.plugins.js by comparing PluginService._init and notification behavior between Chart.js 4.5.0 and 4.5.1. Try to build a minimal chartjs-plugin-datalabels 2.2.0 reproduction from the reported configuration and trace setup, update, and draw hooks. Done means confirming or ruling out the lifecycle regression and documenting a reproducible failure or a focused regression test.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.