BabylonJS/Babylon.js · critical · Error
Unable to create program
Error message
Unable to create program
What it means
_createShaderProgram calls context.createProgram(); if the WebGL context returns null the engine throws "Unable to create program". Null from createProgram means the driver could not allocate a program object — typically a lost context or GPU resource exhaustion.
Source
Thrown at packages/dev/core/src/Engines/thinEngine.functions.ts:174
return pipelineContext;
}
/**
* @internal
*/
export function _createShaderProgram(
pipelineContext: WebGLPipelineContext,
vertexShader: WebGLShader,
fragmentShader: WebGLShader,
context: WebGLContext,
_transformFeedbackVaryings: Nullable<string[]> = null,
validateShaderPrograms?: boolean
): WebGLProgram {
const shaderProgram = context.createProgram();
pipelineContext.program = shaderProgram;
if (!shaderProgram) {
throw new Error("Unable to create program");
}
context.attachShader(shaderProgram, vertexShader);
context.attachShader(shaderProgram, fragmentShader);
context.linkProgram(shaderProgram);
pipelineContext.context = context;
pipelineContext.vertexShader = vertexShader;
pipelineContext.fragmentShader = fragmentShader;
if (!pipelineContext.isParallelCompiled) {
_finalizePipelineContext(pipelineContext, context, validateShaderPrograms);
}
return shaderProgram;
}
View on GitHub (pinned to 0592b347b8)
Solutions
- Check gl.isContextLost(); if lost, wait for webglcontextrestored and rebuild the engine/effect cache.
- Reduce shader program count: merge effects, reuse materials, and dispose unused effects.
- Retry effect creation after resources are released.
- Catch the error at the scene/effect level and fall back to a simpler material.
Example fix
// before
const effect = new Effect(shaderName, attrs, uniforms, engine);
// after
try {
const effect = new Effect(shaderName, attrs, uniforms, engine);
} catch (e) {
if (/Unable to create program/.test(e.message) && engine._gl.isContextLost()) {
await contextRestoredPromise;
effect = new Effect(shaderName, attrs, uniforms, engine);
}
} Defensive patterns
Strategy: retry
Validate before calling
if (engine._gl.isContextLost()) {
await new Promise(r => engine._gl.getExtension('') ?? r); // or listen for webglcontextrestored first
} Type guard
function isEngineContextAlive(engine) {
const gl = (engine as any)._gl;
return !!gl && !gl.isContextLost();
} Try / catch
try {
effect = new Effect(name, attrs, uniforms, engine);
} catch (e) {
if (/Unable to create program/.test(e.message)) {
await contextRestored(engine);
effect = new Effect(name, attrs, uniforms, engine);
}
} Prevention
- Install webglcontextlost/restored handlers that rebuild the effect cache.
- Limit unique shader permutations (variant explosion).
- Dispose effects of removed materials.
When it happens
Trigger: Compiling/linking a shader effect when gl.createProgram() returns null: context lost after device removal, too many live programs, or driver OOM.
Common situations: Tab backgrounded/GPU process crashed during effect compilation, mobile device under memory pressure with hundreds of unique shaders, context restored without rebuilding engine state.
Related errors
- Unable to create multi sampled framebuffer
- Unable to create Occlusion Query
- Unable to create dummy framebuffer
- Unable to create Transform Feedback
- Unable to create uniform buffer
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/fcb26412e9006a35.
Report an issue: GitHub.