You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Uncaught TypeError: Cannot read properties of null (reading 'cancelAnimationFrame') on session end #5844
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:
letanimFrameId=null;functionstartRendering(){animFrameId=requestAnimationFrame(render);}functionstopRendering(){cancelAnimationFrame(animFrameId);// ← animFrameId can be nullanimFrameId=null;}UnderrapidXRsessionswitching,araceconditionexistswhereanimFrameIdissettonullbeforestopRenderingreadsit.ProposedFixAddanull guard:
functionstopRendering(){if(animFrameId!=null){cancelAnimationFrame(animFrameId);}animFrameId=null;}AdditionalContextThisbugwasdiscoveredviaanautomatedcross-hostreplaysystem(WebXRBench)thatreplaysWebXRinteractiontracesacrossdifferentbrowserconfigurations.Theerrorwascapturedin192divergenceinstancesacross17tracesand2A-Frameapps.Severity: Medium—intermittentbutcausesJavaScriptexecutioninterruptionthatcanmanifestasrenderingglitchesorstatecorruption.
Similarly to #5845 there are quite a few factual inaccuracies in this report.
The code in the "Root Cause" section seems to confuse Window.cancelAnimationFrame and XRSession.cancelAnimationFrame. Regardless, it's completely fine to pass a null animation frame callback handle to either. The actual error message indicates that the underlying object was null at the time of the call. It's unclear to me how this could happen, as A-Frame does not call cancelAnimationFrame itself, instead delegating it to Three.js. But ultimately the context is either the window or an XRSession instance during an immersive session, it should never be null.
Please provide the actual stack trace and, if possible, a minimal reproduction. The reproduction steps listed imply manually calling navigator.xr.requestSession('immersive-vr') which isn't the proper way to enter VR in A-Frame.
@XRDeltas Pure speculation from my part, but could it be that your framework creates a proxy XRSession that forwards calls to the actual session? If so, please ensure the session remains spec-compliant after the immersive session has ended. Whenever reporting bugs, please make sure they reproduce without your framework in the mix as well.
Activity
mrxz commentedon Jun 30, 2026
Similarly to #5845 there are quite a few factual inaccuracies in this report.
The code in the "Root Cause" section seems to confuse
Window.cancelAnimationFrameandXRSession.cancelAnimationFrame. Regardless, it's completely fine to pass anullanimation frame callback handle to either. The actual error message indicates that the underlying object wasnullat the time of the call. It's unclear to me how this could happen, as A-Frame does not callcancelAnimationFrameitself, instead delegating it to Three.js. But ultimately the context is either the window or anXRSessioninstance during an immersive session, it should never benull.Please provide the actual stack trace and, if possible, a minimal reproduction. The reproduction steps listed imply manually calling
navigator.xr.requestSession('immersive-vr')which isn't the proper way to enter VR in A-Frame.@XRDeltas Pure speculation from my part, but could it be that your framework creates a proxy
XRSessionthat forwards calls to the actual session? If so, please ensure the session remains spec-compliant after the immersive session has ended. Whenever reporting bugs, please make sure they reproduce without your framework in the mix as well.