Cannot read properties of null (reading 'ownerDocument') in getComputedStyle when canvas is detached during a pending debounced resize
Los mantenedores suelen responder en 1 día
@Yahiro025 ya está trabajando en esto.
Desde el 18/9/2026.
Evaluación
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Aptitud para principiantes
- 58/100
- Tipo de issue
- Error
- Claridad
- Bastante claro
- Estado de actividad
- Activo
- Stack tecnológico
- javascript, typescript
Línea de trabajo
Start in helpers.dom.ts and platform.dom.js, tracing getComputedStyle and getMaximumSize through Chart._resize and the debounced resize callback. Compare the proposed guards with the approach from #11809 and check the related getContainerSize and getRelativePosition paths. Done means a detached canvas during pending resize or teardown no longer throws the reported ownerDocument error.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Description
getStyle/getComputedStyle in helpers.dom.ts (called via getMaximumSize → DomPlatform.getMaximumSize) assumes the canvas element passed to it is never null. When a chart's canvas has already been removed from the DOM but resize()/update() still fires afterward, this throws:
TypeError: Cannot read properties of null (reading 'ownerDocument')
Stack (minified names resolved from source):
getComputedStyle (helpers.dom.ts)
→ getMaximumSize (helpers.dom.ts)
→ DomPlatform.getMaximumSize (platform.dom.js)
→ Chart._resize
→ Chart.detached
→ bindResponsiveEvents
→ bindEvents
→ _checkEventBindings
→ Chart.update
→ this._doResize (debounced resize callback)
Reproduction path
We hit this in a React app (via react-chartjs-2) using resizeDelay (a debounced resize). Sequence:
- Chart mounts; the constructor's resize path schedules a debounced
_doResizebecauseresizeDelay > 0. - Before that debounce timer fires, the component unmounts and React removes the canvas from the DOM (
destroy()runs, but the pending timer isn't always guaranteed to lose its race depending on framework/container teardown order). - The debounced callback fires anyway,
update()→_doResize→detached()→bindResponsiveEvents()→platform.getMaximumSize(canvas, ...)→getComputedStyle(canvas), andcanvasisnull/detached at this point →element.ownerDocumentthrows.
Prior art
This is the same failure #11809 (https://github.com/chartjs/Chart.js/pull/11809) fixed, reported against chart.js 4.4.3. That PR was closed without merging — not because the approach was rejected outright (a maintainer only commented the "return semi-default values" approach felt a bit hacky and asked whether the repro could be narrowed to the container-removal case), but because the author's team moved away from Chart.js before the discussion concluded. The underlying bug was never fixed.
We independently reproduced the identical stack trace and error message against the current latest release, chart.js 4.5.1, confirming it is still present.
Our workaround
We removed our own use of resizeDelay entirely, since a debounced resize is what creates the race between "component removed" and "debounced resize still pending." That avoids the crash for us, but the underlying null-check gap in getComputedStyle/getMaximumSize (and the related spots #11809 touched: getRelativePosition, getContainerSize) remains for anyone else hitting a similar teardown race through a different path (e.g. responsive: true without resizeDelay, combined with fast unmounts during an in-flight ResizeObserver callback).
Suggested fix
Re-open/revive the approach from #11809: guard getComputedStyle/getMaximumSize/getContainerSize/getRelativePosition against a missing canvas (optional chaining + sensible defaults), as that PR's diff already implements.
Environment
- Chart.js: 4.5.1
- Browser: reproduced in Chromium (Playwright) and in production (real user reports, Chrome/Edge on Windows)
- Lenguaje dominante
- JavaScript
- Estrellas
- 67.8k
- Forks
- 12k
- Merge medio
- 1 d 12 h
- PR fusionados (30 d)
- 5
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Sin guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de chartjs/Chart.js
-
fill: 'stack': a dataset's whole fill disappears when its x differs from the line below by ≤ 1e-6 px (happens in animations)Posiblemente ocupada @ump45nose la tomó hace 28 días. Abiertotype: bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
Los mantenedores suelen responder en 1 día
-
Legend pointStyle: 'line' does not apply dataset borderDash patternPosiblemente ocupada @HuzaifaChaudary la tomó hace 61 días. Abiertotype: bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
Los mantenedores suelen responder en 1 día
-
`skipNull` is a configuration option, not a dataset fieldPosiblemente ocupada @puneetdixit200 la tomó hace 147 días. Abiertotype: documentation
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
chartjs/Chart.js#12235 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
type: enhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
Los mantenedores suelen responder en 1 día
Todos los issues de chartjs/Chart.js
Issues similares
-
[Feature Request] [Web] Expose kvCacheQuantizationBits in the onnxruntime-web WebGPU EP optionsAbiertoep:WebGPU platform:web quantization
Dificultad 2/5 1-3 horas Aptitud para principiantes 66/100
microsoft/onnxruntime#33752 ·
Los mantenedores suelen responder en 2 días
-
More Transport Mode IconsAbiertoicon request
Dificultad 2/5 1-3 horas Aptitud para principiantes 66/100
tabler/tabler-icons#1693 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 1-3 horas Aptitud para principiantes 72/100
alvarotrigo/fullPage.js#4755 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 64/100
jlab-sensing/ENTS-backend#854 ·
-
enhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
andromarces/agent-loops#1242 ·
Los mantenedores suelen responder en 1 día