{"record":{"id":"0c472bf010facad7","repo":"fabricjs/fabric.js","slug":"fragment-shader-compile-error-for-this-type","errorCode":null,"errorMessage":"Fragment shader compile error for ${this.type}: ${gl.getShaderInfoLog(\n          fragmentShader,\n        )}","messagePattern":"Fragment shader compile error for (.+?): (.+?)","errorType":"exception","errorClass":"FabricError","httpStatus":null,"severity":"error","filePath":"packages/core/src/filters/BaseFilter.ts","lineNumber":117,"sourceCode":"    if (!vertexShader || !fragmentShader || !program) {\n      throw new FabricError(\n        'Vertex, fragment shader or program creation error',\n      );\n    }\n    gl.shaderSource(vertexShader, vertexSource);\n    gl.compileShader(vertexShader);\n    if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {\n      throw new FabricError(\n        `Vertex shader compile error for ${this.type}: ${gl.getShaderInfoLog(\n          vertexShader,\n        )}`,\n      );\n    }\n\n    gl.shaderSource(fragmentShader, fragmentSource);\n    gl.compileShader(fragmentShader);\n    if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {\n      throw new FabricError(\n        `Fragment shader compile error for ${this.type}: ${gl.getShaderInfoLog(\n          fragmentShader,\n        )}`,\n      );\n    }\n\n    gl.attachShader(program, vertexShader);\n    gl.attachShader(program, fragmentShader);\n    gl.linkProgram(program);\n    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n      throw new FabricError(\n        `Shader link error for \"${this.type}\" ${gl.getProgramInfoLog(program)}`,\n      );\n    }\n\n    const uniformLocations = this.getUniformLocations(gl, program) || {};\n    uniformLocations.uStepW = gl.getUniformLocation(program, 'uStepW');\n    uniformLocations.uStepH = gl.getUniformLocation(program, 'uStepH');","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/fabricjs/fabric.js/blob/2bd4992cabf4ec9609aa349ea09b723cadc94bef/packages/core/src/filters/BaseFilter.ts#L99-L135","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nclass Tint extends fabric.Image.filters.BaseFilter {\n  static type = 'Tint';\n  getFragmentSource() { return 'uniform vec4 uColor; void main() { gl_FragColor = uColor }'; } // missing ;\n}\n\n// after\nclass Tint extends fabric.Image.filters.BaseFilter {\n  static type = 'Tint';\n  getFragmentSource() {\n    return `precision highp float;\nuniform sampler2D uTexture;\nuniform vec4 uColor;\nvoid main() { gl_FragColor = uColor; }`;\n  }\n}","handlingStrategy":"fallback","validationCode":"function fragmentShaderCompiles(src: string): boolean {\n  try {\n    const gl = document.createElement('canvas').getContext('webgl');\n    if (!gl) return false;\n    const s = gl.createShader(gl.FRAGMENT_SHADER);\n    gl.shaderSource(s, src);\n    gl.compileShader(s);\n    return !!gl.getShaderParameter(s, gl.COMPILE_STATUS);\n  } catch { return false; }\n}\nif (fragmentShaderCompiles(myFilter.getFragmentSource())) { /* safe to apply */ }","typeGuard":"const isValidFragmentSource = (src: string): boolean => {\n  try {\n    const gl = document.createElement('canvas').getContext('webgl');\n    if (!gl) return false;\n    const s = gl.createShader(gl.FRAGMENT_SHADER)!;\n    gl.shaderSource(s, src); gl.compileShader(s);\n    return !!gl.getShaderParameter(s, gl.COMPILE_STATUS);\n  } catch { return false; }\n};","tryCatchPattern":"try {\n  img.applyFilters();\n} catch (e) {\n  if (e instanceof Error && e.message.includes('Fragment shader compile error')) {\n    console.error(e.message); // contains filter type + GLSL info log\n    img.filters = []; // or swap in a known-good filter\n  } else throw e;\n}","preventionTips":["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."],"tags":["fabricjs","webgl","glsl","shader-compile","fragment-shader"],"backgroundTag":"shader-compilation-failed","analyzedSha":"2bd4992cabf4ec9609aa349ea09b723cadc94bef","analyzedAt":"2026-08-28T10:56:44.286Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}