BabylonJS/Babylon.js · error · Error
${error}
Error message
${error} What it means
Thrown when the WebGL program fails to LINK after both shaders compiled individually. _finalizePipelineContext calls context.getProgramInfoLog(program) and throws the raw link log, storing it in pipelineContext.programLinkError. Compilation of each shader succeeded, but glLinkProgram found incompatibilities between them.
Source
Thrown at packages/dev/core/src/Engines/thinEngine.functions.ts:245
if (log) {
pipelineContext.vertexCompilationError = log;
throw new Error("VERTEX SHADER " + log);
}
}
// Fragment
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
const log = gl.getShaderInfoLog(fragmentShader);
if (log) {
pipelineContext.fragmentCompilationError = log;
throw new Error("FRAGMENT SHADER " + log);
}
}
const error = context.getProgramInfoLog(program);
if (error) {
pipelineContext.programLinkError = error;
throw new Error(error);
}
}
if (/*this.*/ validateShaderPrograms) {
context.validateProgram(program);
const validated = context.getProgramParameter(program, context.VALIDATE_STATUS);
if (!validated) {
const error = context.getProgramInfoLog(program);
if (error) {
pipelineContext.programValidationError = error;
throw new Error(error);
}
}
}
context.deleteShader(vertexShader);
context.deleteShader(fragmentShader);
View on GitHub (pinned to 0592b347b8)
Solutions
- Read the thrown log — it typically says which varying/attribute is mismatched or which limit was exceeded
- Make varying/in-out declarations match exactly (name, type, precision) between vertex and fragment shaders
- Reduce the number of varyings/attributes if the log mentions limits
- Inspect pipelineContext.programLinkError for the stored log when handling the error
Example fix
// before vertex: `varying vec2 vUv; ...` fragment: `varying vec2 UV; ...` // name mismatch // after vertex: `varying vec2 vUv; ...` fragment: `varying vec2 vUv; ...`
Defensive patterns
Strategy: validation
Validate before calling
function checkVaryingsMatch(vertexSrc: string, fragmentSrc: string): string[] {
const decl = /(?:varying|out)\s+\w+\s+(\w+)\s*;/g;
const outs = new Set<string>(); let m;
while ((m = decl.exec(vertexSrc))) outs.add(m[1]);
const ins = /(?:varying|in)\s+\w+\s+(\w+)\s*;/g;
const missing: string[] = [];
while ((m = ins.exec(fragmentSrc))) outs.delete(m[1]);
return [...outs]; // varyings declared in vertex but missing in fragment
} Type guard
function isLinkError(e: unknown): e is Error & { pipelineProgramLinkError?: string } {
return e instanceof Error && !e.message.startsWith('FRAGMENT SHADER');
} Try / catch
try {
engine.createEffect(...);
} catch (e) {
const msg = (e as Error).message;
if (!msg.startsWith('FRAGMENT SHADER') && !msg.startsWith('VERTEX')) {
console.error('Program link failed:', msg); // raw link log
}
} Prevention
- Keep varying/in-out declarations in a shared GLSL snippet to guarantee they match
- Rename varyings via find-all across both stages
- Count varyings against engine._gl.getParameter(gl.MAX_VARYINGS) for big shaders
- Test on mobile GPUs early; they enforce tighter limits
When it happens
Trigger: Vertex and fragment shaders that compile alone but don't link: varying/in variables with mismatched names, types, or precision between stages; an out variable in vertex shader never declared as in/out in fragment; too many attributes or varyings exceeding GPU limits.
Common situations: Hand-written ShaderMaterial where vertex and fragment strings were edited independently; renaming a varying in one stage only; using 'varying' in WebGL2 without #version 300 es handling; exceeding maxVaryings on low-end/mobile GPUs.
Related errors
- VERTEX SHADER ${log}
- FRAGMENT SHADER ${log}
- Atmosphere is not supported on WebGL ${engine.version}.
- Instanced arrays are required for MSDF text rendering.
- Unable to create multi sampled framebuffer
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/134e851f15942af7.
Report an issue: GitHub.