fabricjs/fabric.js · error · FabricError
Fragment shader compile error for ${this.type}: ${gl.getShad
Error message
Fragment shader compile error for ${this.type}: ${gl.getShaderInfoLog(
fragmentShader,
)} What it means
Fabric's BaseFilter.createProgram compiles each filter's fragment shader (the GLSL that implements the filter effect) and checks gl.getShaderParameter(COMPILE_STATUS). A false status throws this error, embedding the filter type and the GLSL compiler info log so you can see the exact failing line. It's the fragment-stage counterpart of the vertex compile error and is the one you'll hit from bad custom GLSL, since each filter's unique code lives in the fragment shader.
Source
Thrown at packages/core/src/filters/BaseFilter.ts:117
if (!vertexShader || !fragmentShader || !program) {
throw new FabricError(
'Vertex, fragment shader or program creation error',
);
}
gl.shaderSource(vertexShader, vertexSource);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
throw new FabricError(
`Vertex shader compile error for ${this.type}: ${gl.getShaderInfoLog(
vertexShader,
)}`,
);
}
gl.shaderSource(fragmentShader, fragmentSource);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
throw new FabricError(
`Fragment shader compile error for ${this.type}: ${gl.getShaderInfoLog(
fragmentShader,
)}`,
);
}
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
throw new FabricError(
`Shader link error for "${this.type}" ${gl.getProgramInfoLog(program)}`,
);
}
const uniformLocations = this.getUniformLocations(gl, program) || {};
uniformLocations.uStepW = gl.getUniformLocation(program, 'uStepW');
uniformLocations.uStepH = gl.getUniformLocation(program, 'uStepH');View on GitHub (pinned to 2bd4992cab)
Solutions
- Read the included info log — it pinpoints the GLSL line and error; fix the fragment source in your custom filter.
- Declare `precision highp float;`/`precision mediump float;` and match uniform/varying names exactly with what the filter registers.
- Ensure GLSL version compatibility (WebGL1-style texture2D / varying vs WebGL3-style) with the context fabric uses; prefer fabric's own source patterns as a template.
- For built-in filters, recreate the context (possible loss/reset) and retry; disable filters if the environment can't compile them.
Example fix
// before
class Tint extends fabric.Image.filters.BaseFilter {
static type = 'Tint';
getFragmentSource() { return 'uniform vec4 uColor; void main() { gl_FragColor = uColor }'; } // missing ;
}
// after
class Tint extends fabric.Image.filters.BaseFilter {
static type = 'Tint';
getFragmentSource() {
return `precision highp float;
uniform sampler2D uTexture;
uniform vec4 uColor;
void main() { gl_FragColor = uColor; }`;
}
} Defensive patterns
Strategy: fallback
Validate before calling
function fragmentShaderCompiles(src: string): boolean {
try {
const gl = document.createElement('canvas').getContext('webgl');
if (!gl) return false;
const s = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(s, src);
gl.compileShader(s);
return !!gl.getShaderParameter(s, gl.COMPILE_STATUS);
} catch { return false; }
}
if (fragmentShaderCompiles(myFilter.getFragmentSource())) { /* safe to apply */ } Type guard
const isValidFragmentSource = (src: string): boolean => {
try {
const gl = document.createElement('canvas').getContext('webgl');
if (!gl) return false;
const s = gl.createShader(gl.FRAGMENT_SHADER)!;
gl.shaderSource(s, src); gl.compileShader(s);
return !!gl.getShaderParameter(s, gl.COMPILE_STATUS);
} catch { return false; }
}; Try / catch
try {
img.applyFilters();
} catch (e) {
if (e instanceof Error && e.message.includes('Fragment shader compile error')) {
console.error(e.message); // contains filter type + GLSL info log
img.filters = []; // or swap in a known-good filter
} else throw e;
} Prevention
- Precompile custom fragment sources once (validation above) instead of discovering failures during applyFilters.
- Declare precision and match uniform names exactly with the filter's uniform registration.
- Model custom filters on fabric's built-in filters' GLSL to stay version-compatible.
- Keep an unfiltered fallback path for environments where compilation fails.
When it happens
Trigger: Applying a filter whose fragment source is invalid: custom subclasses overriding getFragmentSource (or GLSL maps) with syntax errors, unsupported extensions, missing precision qualifiers, or wrong varying/uniform declarations; also broken drivers/context loss for built-in filters.
Common situations: Writing a custom fabric.Image.filters.BaseFilter subclass with GLSL mistakes (missing semicolons, undeclared uniforms, texture2D vs texture in WebGL2); copy-pasting WebGL1 GLSL into a WebGL2-only context; driver bugs on older mobile GPUs.
Related errors
- Vertex shader compile error for ${this.type}: ${gl.getShader
- Vertex, fragment shader or program creation error
- Shader link error for "${this.type}" ${gl.getProgramInfoLog(
- No class registered for ${classType}
- Trying to initialize a canvas that has already been initiali
AI-assisted analysis of fabricjs/fabric.js@2bd4992cab (2026-08-28).
Data as JSON: /api/errors/0c472bf010facad7.
Report an issue: GitHub.