{"record":{"id":"79fe451a76323d42","repo":"BabylonJS/Babylon.js","slug":"clientwaitsync-failed","errorCode":null,"errorMessage":"clientWaitSync failed","messagePattern":"clientWaitSync failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/Engines/engine.pure.ts","lineNumber":1006,"sourceCode":"        return result;\r\n    }\r\n\r\n    /**\r\n     * Delete a webGL buffer used with instantiation\r\n     * @param buffer defines the webGL buffer to delete\r\n     */\r\n    public deleteInstancesBuffer(buffer: WebGLBuffer): void {\r\n        this._gl.deleteBuffer(buffer);\r\n    }\r\n\r\n    private async _clientWaitAsync(sync: WebGLSync, flags = 0, intervalms = 10): Promise<void> {\r\n        const gl = <WebGL2RenderingContext>(this._gl as any);\r\n        return await new Promise((resolve, reject) => {\r\n            _RetryWithInterval(\r\n                () => {\r\n                    const res = gl.clientWaitSync(sync, flags, 0);\r\n                    if (res == gl.WAIT_FAILED) {\r\n                        throw new Error(\"clientWaitSync failed\");\r\n                    }\r\n                    if (res == gl.TIMEOUT_EXPIRED) {\r\n                        return false;\r\n                    }\r\n                    return true;\r\n                },\r\n                resolve,\r\n                reject,\r\n                intervalms\r\n            );\r\n        });\r\n    }\r\n\r\n    /**\r\n     * This function might return null synchronously, so it is technically not async.\r\n     * @internal\r\n     */\r\n    // eslint-disable-next-line no-restricted-syntax\r","sourceCodeStart":988,"sourceCodeEnd":1024,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Engines/engine.pure.ts#L988-L1024","documentation":"This comes from the engine's async readback path (based on gl.clientWaitSync / fence sync). If the sync object wait returns WAIT_FAILED — the sync object is invalid, the context is lost, or the fence was never signaled properly — the retry loop throws \"clientWaitSync failed\".","triggerScenarios":"Awaiting _readPixelsAsync (or similar fence-based GPU->CPU readback) when the WebGL2 context is lost, the sync object was created on a different context, or a driver-level fence error occurs.","commonSituations":"Background tab / GPU process crash mid-readback, mobile browser context loss during long-running apps, calling readback after the engine or texture was disposed.","solutions":["Check gl.isContextLost() in the catch handler; if lost, rebuild the engine and retry the readback after restore.","Ensure the texture/framebuffer still exists and wasn't disposed between issuing the readback and awaiting the promise.","Retry the readback operation once after a frame; transient WAIT_FAILED can occur on some drivers.","Fall back to synchronous readPixels if async readback repeatedly fails."],"exampleFix":"// before\nconst data = await engine._readPixelsAsync(x, y, w, h, fmt, type, buffer);\n// after\ntry {\n  const data = await engine._readPixelsAsync(x, y, w, h, fmt, type, buffer);\n} catch (e) {\n  if (String(e).includes(\"clientWaitSync\")) {\n    engine._gl.isContextLost()\n      ? rebuildEngineAndRedoReadback()\n      : readPixelsFallback();\n  }\n}","handlingStrategy":"retry","validationCode":"function canAwaitReadback(engine) {\n  return engine.webGLVersion >= 2 && !engine._gl.isContextLost();\n}","typeGuard":"function isReadbackSafe(engine, sync) {\n  return engine.webGLVersion >= 2 && !engine._gl.isContextLost() && !!sync;\n}","tryCatchPattern":"try {\n  await readbackPromise;\n} catch (e) {\n  if (/clientWaitSync failed/.test(e.message)) {\n    if (engine._gl.isContextLost()) scheduleEngineRebuild();\n    else retryReadbackOnce();\n  }\n}","preventionTips":["Await readbacks promptly; don't dispose textures/framebuffers between issue and await.","Monitor webglcontextlost so in-flight fences are invalidated.","Keep a synchronous readPixels fallback path."],"tags":["webgl2","async","readback","context-loss"],"backgroundTag":"gpu-fence-wait-failed","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}