{"record":{"id":"cddc63e67deb10d0","repo":"phaserjs/phaser","slug":"matter-runner-missing-required-global-window-canc","errorCode":null,"errorMessage":"Matter.Runner: missing required global window.cancelAnimationFrame.","messagePattern":"Matter\\.Runner: missing required global window\\.cancelAnimationFrame\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/physics/matter-js/lib/core/Runner.js","lineNumber":208,"sourceCode":"    /**\n     * Alias for `Runner.run`.\n     * @method start\n     * @param {runner} runner\n     * @param {engine} engine\n     */\n    Runner._onNextFrame = function(runner, callback) {\n        if (typeof window !== 'undefined' && window.requestAnimationFrame) {\n            runner.frameRequestId = window.requestAnimationFrame(callback);\n        } else {\n            throw new Error('Matter.Runner: missing required global window.requestAnimationFrame.');\n        }\n        return runner.frameRequestId;\n    };\n    Runner._cancelNextFrame = function(runner) {\n        if (typeof window !== 'undefined' && window.cancelAnimationFrame) {\n            window.cancelAnimationFrame(runner.frameRequestId);\n        } else {\n            throw new Error('Matter.Runner: missing required global window.cancelAnimationFrame.');\n        }\n    };\n\n    var _mean = function(values) {\n        var result = 0,\n            valuesLength = values.length;\n        for (var i = 0; i < valuesLength; i += 1) {\n            result += values[i];\n        }\n        return (result / valuesLength) || 0;\n    };\n    Runner._mean = _mean;\n    /*\n    *\n    *  Events Documentation\n    *\n    */\n","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/phaserjs/phaser/blob/41be1e462bc600064e498cba370bfa8c5c055a22/src/physics/matter-js/lib/core/Runner.js#L190-L226","documentation":"Runner.js:208 throws from `_cancelNextFrame` when `window.cancelAnimationFrame` is missing. The Runner calls this to cancel a pending frame on stop/pause; without it cleanup cannot proceed safely and Matter throws rather than leak a scheduled callback.","triggerScenarios":"Calling `Runner.stop(runner)` or `Runner.pause(runner)` (or Phaser's Matter physics shutdown) in an environment where `window.requestAnimationFrame` exists but `cancelAnimationFrame` does not, or where neither exists (Node/jsdom).","commonSituations":"Stopping a Matter Runner in a partial browser shim (some test harnesses define rAF but not cRAF); SSR teardown; an environment where `window` exists but is incompletely polyfilled.","solutions":["Polyfill `globalThis.cancelAnimationFrame` (e.g. via `clearTimeout`) before using the Runner.","Avoid `Runner.run`/`Runner.stop` under Node — drive `Engine.update` manually and skip frame scheduling entirely.","Ensure both rAF and cRAF are present together when polyfilling."],"exampleFix":"// before (partial shim has rAF but not cRAF)\nRunner.stop(runner) // throws\n// after\nglobalThis.cancelAnimationFrame = globalThis.cancelAnimationFrame || (id => clearTimeout(id))\nRunner.stop(runner)","handlingStrategy":"validation","validationCode":"if (typeof window === 'undefined' || typeof window.cancelAnimationFrame !== 'function') {\n  globalThis.cancelAnimationFrame = globalThis.cancelAnimationFrame || (id => clearTimeout(id))\n}\nRunner.stop(runner)","typeGuard":"const supportsCancelRAF = () => typeof window !== 'undefined' && typeof window.cancelAnimationFrame === 'function'","tryCatchPattern":null,"preventionTips":["Polyfill both rAF and cRAF together; partial polyfills cause this error.","Under Node, avoid Runner entirely and use manual Engine.update.","Verify the environment's window shim is complete before using the Runner."],"tags":["physics","matter-js","environment","requestanimationframe"],"backgroundTag":null,"analyzedSha":"41be1e462bc600064e498cba370bfa8c5c055a22","analyzedAt":"2026-08-13T04:23:39.729Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}