{"record":{"id":"c68f54fa9cbd6bbf","repo":"BabylonJS/Babylon.js","slug":"unable-to-create-program","errorCode":null,"errorMessage":"Unable to create program","messagePattern":"Unable to create program","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"packages/dev/core/src/Engines/engine.pure.ts","lineNumber":631,"sourceCode":"\r\n        const program = super.createShaderProgram(pipelineContext, vertexCode, fragmentCode, defines, context, transformFeedbackVaryings);\r\n        this.onAfterShaderCompilationObservable.notifyObservers(this);\r\n\r\n        return program;\r\n    }\r\n\r\n    protected override _createShaderProgram(\r\n        pipelineContext: WebGLPipelineContext,\r\n        vertexShader: WebGLShader,\r\n        fragmentShader: WebGLShader,\r\n        context: WebGLRenderingContext,\r\n        transformFeedbackVaryings: Nullable<string[]> = null\r\n    ): WebGLProgram {\r\n        const shaderProgram = context.createProgram();\r\n        pipelineContext.program = shaderProgram;\r\n\r\n        if (!shaderProgram) {\r\n            throw new Error(\"Unable to create program\");\r\n        }\r\n\r\n        context.attachShader(shaderProgram, vertexShader);\r\n        context.attachShader(shaderProgram, fragmentShader);\r\n\r\n        if (this.webGLVersion > 1 && transformFeedbackVaryings) {\r\n            const transformFeedback = this.createTransformFeedback();\r\n\r\n            this.bindTransformFeedback(transformFeedback);\r\n            this.setTranformFeedbackVaryings(shaderProgram, transformFeedbackVaryings);\r\n            pipelineContext.transformFeedback = transformFeedback;\r\n        }\r\n\r\n        context.linkProgram(shaderProgram);\r\n\r\n        if (this.webGLVersion > 1 && transformFeedbackVaryings) {\r\n            this.bindTransformFeedback(null);\r\n        }\r","sourceCodeStart":613,"sourceCodeEnd":649,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Engines/engine.pure.ts#L613-L649","documentation":"When compiling a shader program, context.createProgram() returned null and Babylon throws 'Unable to create program'. WebGL returns null for createProgram when the context is lost or exhausted (too many programs/contexts), so the engine aborts instead of attaching shaders to an invalid program handle.","triggerScenarios":"Creating a shader/program (engine.createShaderProgram path) after a WebGL context loss; too many simultaneously live programs or contexts in the page; GPU driver returning null under resource pressure.","commonSituations":"Long-running apps that never release shader programs hitting program-count limits; mobile browsers/Safari context loss; running many Babylon engines in one tab and exceeding context limits.","solutions":["Handle context loss: listen to engine.onContextLost / contextlost event and call engine.restoreDestroyedDualBuffers or reload the engine","Reduce program count: reuse effects/materials, call releaseEffects/releaseCompiledShaders when done","Check for context-lost state before compiling and wait for restore (webglcontextrestored)","Split heavy scenes into separate pages/iframes to avoid hitting context/program limits"],"exampleFix":"// before\nconst effect = engine.createEffect('myShader', ...); // throws if context lost\n// after\nengine.onContextLostObservable.add(() => console.warn('context lost; pausing renders'));\nengine.onContextRestoredObservable.add(() => rebuildShaders());\nif (!engine._gl?.isContextLost()) {\n  const effect = engine.createEffect('myShader', ...);\n}","handlingStrategy":"try-catch","validationCode":"const gl = (engine as any)._gl as WebGL2RenderingContext;\nif (!gl || gl.isContextLost()) {\n  await waitForContextRestored(engine); // listen for webglcontextrestored before compiling\n}","typeGuard":"function glReady(engine: AbstractEngine): engine is AbstractEngine & { _gl: WebGL2RenderingContext } {\n  const gl = (engine as any)._gl;\n  return !!gl && !gl.isContextLost();\n}","tryCatchPattern":"try {\n  effect = engine.createEffect(name, attrs, uniforms, samplers, defines);\n} catch (e) {\n  if (e instanceof Error && e.message === 'Unable to create program') {\n    await new Promise(res => engine.onContextRestoredObservable.addOnce(res));\n    effect = engine.createEffect(name, attrs, uniforms, samplers, defines); // retry after restore\n  } else throw e;\n}","preventionTips":["Register onContextLost/onContextRestored handlers at engine startup","Cap live programs: releaseEffects/releaseCompiledShaders on unused materials","Avoid creating many engines in one page (browser context limits)","Detect context loss via gl.isContextLost() before compiling shaders"],"tags":["webgl","shader-program","context-loss","gpu-resource"],"backgroundTag":"webgl-create-program-null","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}