{"record":{"id":"9c2d40995a62309b","repo":"fabricjs/fabric.js","slug":"vertex-fragment-shader-or-program-creation-error","errorCode":null,"errorMessage":"Vertex, fragment shader or program creation error","messagePattern":"Vertex, fragment shader or program creation error","errorType":"exception","errorClass":"FabricError","httpStatus":null,"severity":"error","filePath":"packages/core/src/filters/BaseFilter.ts","lineNumber":100,"sourceCode":"    gl: WebGLRenderingContext,\n    fragmentSource: string = this.getFragmentSource(),\n    vertexSource: string = this.getVertexSource(),\n  ) {\n    const {\n      WebGLProbe: { GLPrecision = 'highp' },\n    } = getEnv();\n    if (GLPrecision !== 'highp') {\n      fragmentSource = fragmentSource.replace(\n        regex,\n        highPsourceCode.replace('highp', GLPrecision),\n      );\n    }\n    const vertexShader = gl.createShader(gl.VERTEX_SHADER);\n    const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\n    const program = gl.createProgram();\n\n    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(","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/fabricjs/fabric.js/blob/2bd4992cabf4ec9609aa349ea09b723cadc94bef/packages/core/src/filters/BaseFilter.ts#L82-L118","documentation":"When a WebGL filter is applied, Fabric compiles its GLSL shaders via gl.createShader/gl.createProgram. If any of these WebGL calls returns null/falsy (the context failed to allocate shader or program objects), this generic creation error is thrown before compilation is even attempted. It almost always indicates a broken or resource-exhausted WebGL context rather than a shader bug.","triggerScenarios":"Applying any filter (e.g. fabric.Image.filters.Blur) when the WebGL context is lost, was force-destroyed, has run out of GPU resources, or when a non-WebGL/noop context is used. Repeatedly creating filters/contexts without cleanup can exhaust resources and make createShader/createProgram return null.","commonSituations":"WebGL context loss on mobile browsers or after GPU driver resets; too many canvases/contexts open (browsers cap active contexts); running in headless/CI environments without proper GPU support; memory pressure from many large filtered images.","solutions":["Reuse a single canvas/context and dispose filters/images properly so contexts aren't leaked (browsers limit live WebGL contexts).","Handle context loss: listen for `webglcontextlost` and re-create the canvas/filters, or reload after restoring the context.","Verify the environment supports WebGL (headless CI may need --use-gl=swiftshader or a GPU); fall back to no filter or 2D-only processing.","If reproducible with one filter, test in a clean page to rule out resource exhaustion from other code."],"exampleFix":"// before\nimg.filters = [new fabric.Image.filters.Blur({ blur: 0.5 })];\nimg.applyFilters(); // may throw if WebGL resources are exhausted\n\n// after\n// limit live contexts, dispose unused canvases\noldCanvas.dispose();\nimg.filters = [new fabric.Image.filters.Blur({ blur: 0.5 })];\nimg.applyFilters();","handlingStrategy":"fallback","validationCode":"function webglAvailable(): boolean {\n  try {\n    const c = document.createElement('canvas');\n    return !!(c.getContext('webgl') || c.getContext('experimental-webgl'));\n  } catch { return false; }\n}\nif (!webglAvailable()) img.filters = []; // skip filters","typeGuard":"const canUseFilters = (canvas: HTMLCanvasElement): boolean =>\n  !!canvas.getContext('webgl2') || !!canvas.getContext('webgl');","tryCatchPattern":"try {\n  img.applyFilters();\n} catch (e) {\n  if (e instanceof Error && /shader or program creation error/.test(e.message)) {\n    img.filters = []; // degrade gracefully without filters\n    img.applyFilters();\n  } else throw e;\n}","preventionTips":["Dispose unused canvases and filters to avoid exhausting the browser's WebGL context limit.","Listen for webglcontextlost and rebuild the canvas/filters when it fires.","Test on low-end/mobile GPUs and provide a no-filter fallback path."],"tags":["fabricjs","webgl","filters","gpu-resources","context-loss"],"backgroundTag":"webgl-context-failure","analyzedSha":"2bd4992cabf4ec9609aa349ea09b723cadc94bef","analyzedAt":"2026-08-28T10:56:44.286Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}