{"record":{"id":"76df7d776d8b6459","repo":"gfx-rs/wgpu","slug":"could-not-create-shader-program-76df7d","errorCode":null,"errorMessage":"Could not create shader program","messagePattern":"Could not create shader program","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"wgpu-hal/src/gles/web.rs","lineNumber":322,"sourceCode":"                    0,\n                    swapchain.extent.height as i32,\n                    swapchain.extent.width as i32,\n                    0,\n                    0,\n                    0,\n                    swapchain.extent.width as i32,\n                    swapchain.extent.height as i32,\n                    glow::COLOR_BUFFER_BIT,\n                    glow::NEAREST,\n                )\n            };\n        }\n\n        Ok(())\n    }\n\n    unsafe fn create_srgb_present_program(gl: &glow::Context) -> glow::Program {\n        let program = unsafe { gl.create_program() }.expect(\"Could not create shader program\");\n        let vertex =\n            unsafe { gl.create_shader(glow::VERTEX_SHADER) }.expect(\"Could not create shader\");\n        unsafe { gl.shader_source(vertex, include_str!(\"./shaders/srgb_present.vert\")) };\n        unsafe { gl.compile_shader(vertex) };\n        let fragment =\n            unsafe { gl.create_shader(glow::FRAGMENT_SHADER) }.expect(\"Could not create shader\");\n        unsafe { gl.shader_source(fragment, include_str!(\"./shaders/srgb_present.frag\")) };\n        unsafe { gl.compile_shader(fragment) };\n        unsafe { gl.attach_shader(program, vertex) };\n        unsafe { gl.attach_shader(program, fragment) };\n        unsafe { gl.link_program(program) };\n        unsafe { gl.delete_shader(vertex) };\n        unsafe { gl.delete_shader(fragment) };\n        unsafe { gl.bind_texture(glow::TEXTURE_2D, None) };\n\n        program\n    }\n","sourceCodeStart":304,"sourceCodeEnd":340,"githubUrl":"https://github.com/gfx-rs/wgpu/blob/3e11ff59bf3f9795d285ecc045014089640d7248/wgpu-hal/src/gles/web.rs#L304-L340","documentation":"This panic comes from `create_srgb_present_program` in the WebGL/GLES backend when `gl.create_program()` returns a null/invalid program object. glow returns a `NativeProgram` whose truthiness reflects whether the underlying GL call succeeded, so a null result is unwrapped with `.expect(...)`. It means the WebGL context could not allocate a new program object, typically because the context is lost or the implementation limit on program objects has been reached.","triggerScenarios":"Calling `Adapter::new` / instance initialization on the WebGL backend at the moment wgpu sets up its internal sRGB present program (`create_srgb_present_program`), when the browser's WebGL context is lost, the context is not current, or the per-context program object limit (e.g. `gl.getParameter(gl.NUM_PROGRAM_BINARY_FORMATS)`-style limits) is exhausted.","commonSituations":"Long-running single-page apps that leak WebGL programs/context hits until context loss; browsers throttling or killing GPU processes for background tabs; creating too many wgpu instances/devices in one page; embedding canvas in a page where WebGL was blocked or GPU blacklist forced software rendering that then failed.","solutions":["Check for WebGL context loss (`canvas.addEventListener('webglcontextlost', ...)`) and reinitialize the wgpu device when it fires.","Reduce the number of programs/context: reuse a single Instance/Device/Surface instead of creating new ones per component or frame.","Verify the canvas/context is valid and not blocked: test `canvas.getContext('webgl2')` directly in the browser console and check `WEBGL_lose_context` extension state.","Update browser/GPU drivers or force hardware acceleration on; software renderers (SwiftShader) can fail program creation under memory pressure."],"exampleFix":"// before: panic on null program\nlet program = unsafe { gl.create_program() }.expect(\"Could not create shader program\");\n// after: handle creation failure gracefully\nlet program = unsafe { gl.create_program() }\n    .ok_or(crate::CreateDeviceError::OutOfMemory)?;","handlingStrategy":"try-catch","validationCode":"const gl = canvas.getContext('webgl2');\nif (!gl || gl.isContextLost()) {\n  throw new Error('WebGL2 context unavailable or lost before creating wgpu device');\n}\ncanvas.addEventListener('webglcontextlost', (e) => { e.preventDefault(); scheduleReinit(); });","typeGuard":"function hasLiveContext(gl: WebGL2RenderingContext | null): gl is WebGL2RenderingContext {\n  return gl !== null && !gl.isContextLost();\n}","tryCatchPattern":"// Rust: wrap device creation and fall back instead of panicking\nmatch instance.request_adapter(&desc).and_then(|a| a.request_device(&dev_desc)) {\n  Ok(device) => start(device),\n  Err(e) => { log::error!(\"GPU init failed: {e}\"); show_fallback_ui(); }\n}\n// JS edge: catch wasm_bindgen thrown panics around init\ntry { await init_wgpu(canvas); } catch (e) { showFallback('WebGL unavailable'); }","preventionTips":["Register webglcontextlost/webglcontextrestored listeners on the canvas before creating wgpu resources.","Create one Instance/Device/Surface per page and reuse it; never create them per frame or per component mount.","Check gl.isContextLost() before initializing and before any surface recreation.","Keep GPU memory usage modest to avoid browser GPU-process OOM that triggers context loss."],"tags":["webgl","gles","shader-program","context-loss","panic"],"backgroundTag":"gl-resource-creation-failed","analyzedSha":"3e11ff59bf3f9795d285ecc045014089640d7248","analyzedAt":"2026-09-03T01:43:21.459Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T07:17:11.731Z"}