Uncaught TypeError: Cannot read properties of null (reading 'cancelAnimationFrame') on session end
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 68/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- javascript
- Domain
- computer-graphics, web-dev
Research direction
Start in the render-loop implementation around stopRendering in aframe.js, then reproduce repeated WebXR session exits and re-entries using the A-Painter scenario described. Confirm that session transitions no longer throw the reported cancelAnimationFrame error and that rendering continues normally.
Written by the indexing model from the issue text.
Description
Description
When an A-Frame application ends an XR session and immediately re-enters, an Uncaught TypeError: Cannot read properties of null (reading 'cancelAnimationFrame') is thrown. This intermittently crashes the application during XR session lifecycle transitions.
The root cause is in A-Frame's render loop: cancelAnimationFrame is called with a null handle when the animation frame ID is cleaned up before the stop function reads it.
Environment
- A-Frame version: Latest (affects A-Painter, A-Blast, and other A-Frame WebXR apps)
- Browser: Chromium 124+ (mobile emulation triggers more frequently)
- XR Mode: WebXR
immersive-vr
Steps to Reproduce
- Open an A-Frame WebXR app (e.g., A-Painter)
- Enter VR (
navigator.xr.requestSession('immersive-vr')) - Perform interactions (select, aim)
- Exit VR (end the session)
- Re-enter VR immediately
- Repeat steps 4-5 multiple times
Expected Behavior
cancelAnimationFrame should gracefully handle a null handle, or the animation frame handle should never be null during the render loop.
Actual Behavior
Uncaught TypeError: Cannot read properties of null (reading 'cancelAnimationFrame') at stopRendering (aframe.js:XXXX)
Observed in ~15% of replay traces (3 out of 19 traces for A-Painter on mobile Chromium).
Root Cause
In A-Frame's render loop, the cancelAnimationFrame call does not guard against null:
let animFrameId = null;
function startRendering() {
animFrameId = requestAnimationFrame(render);
}
function stopRendering() {
cancelAnimationFrame(animFrameId); // ← animFrameId can be null
animFrameId = null;
}
Under rapid XR session switching, a race condition exists where animFrameId is set to null before stopRendering reads it.
Proposed Fix
Add a null guard:
function stopRendering() {
if (animFrameId != null) {
cancelAnimationFrame(animFrameId);
}
animFrameId = null;
}
Additional Context
This bug was discovered via an automated cross-host replay system (WebXRBench) that replays WebXR interaction traces across different browser configurations. The error was captured in 192 divergence instances across 17 traces and 2 A-Frame apps.
Severity: Medium — intermittent but causes JavaScript execution interruption that can manifest as rendering glitches or state corruption.
- Dominant language
- JavaScript
- Stars
- 17.6k
- Forks
- 4.4k
- PR merge metrics
- No merged PRs in 30d
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from aframevr/aframe
-
TypeError: session.requestAnimationFrame is not a function when re-entering XR session after exit Open
Difficulty 4/5 3-5 days Newbie friendliness 55/100
-
tracked-controls-webxr does not update entity position when referenceSpaceType is bounded-floor Open
Difficulty 4/5 3-5 days Newbie friendliness 55/100
-
Difficulty 3/5 1-2 days Newbie friendliness 45/100
-
Difficulty 5/5 Over a week Newbie friendliness 25/100
-
Difficulty 3/5 1-2 days Newbie friendliness 58/100
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
HarperFast/skills#96 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Automattic/studio#4908 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
sugarlabs/musicblocks#8847 ·
-
client-controller-update ta-bot-triage team-money-movement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
MetaMask/metamask-mobile#36594 ·