{"record":{"id":"c3f7e333ddd8aba3","repo":"GraphiteEditor/Graphite","slug":"failed-to-create-surface-from-canvas","errorCode":null,"errorMessage":"Failed to create surface from canvas","messagePattern":"Failed to create surface from canvas","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"node-graph/libraries/canvas-utils/src/wasm.rs","lineNumber":68,"sourceCode":"\t\tself.get().set_resolution(resolution);\n\t}\n}\n\n#[cfg(feature = \"wgpu\")]\npub struct CanvasSurfaceHandle(CanvasHandle, Option<Arc<WgpuSurface>>);\n#[cfg(feature = \"wgpu\")]\nimpl CanvasSurfaceHandle {\n\tpub fn new() -> Self {\n\t\tSelf(CanvasHandle::new(), None)\n\t}\n\tfn surface(&mut self, executor: &WgpuExecutor) -> &WgpuSurface {\n\t\tif self.1.is_none() {\n\t\t\tlet canvas = self.0.get().canvas.clone();\n\t\t\tlet surface = executor\n\t\t\t\t.context()\n\t\t\t\t.instance\n\t\t\t\t.create_surface(wgpu::SurfaceTarget::Canvas(canvas))\n\t\t\t\t.expect(\"Failed to create surface from canvas\");\n\t\t\tself.1 = Some(Arc::new(surface));\n\t\t}\n\t\tself.1.as_ref().unwrap()\n\t}\n}\n#[cfg(feature = \"wgpu\")]\nimpl Canvas for CanvasSurfaceHandle {\n\tfn id(&mut self) -> CanvasId {\n\t\tself.0.id()\n\t}\n\tfn context(&mut self) -> CanvasRenderingContext2d {\n\t\tself.0.context()\n\t}\n\tfn set_resolution(&mut self, resolution: glam::UVec2) {\n\t\tself.0.set_resolution(resolution);\n\t}\n}\n#[cfg(feature = \"wgpu\")]","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/node-graph/libraries/canvas-utils/src/wasm.rs#L50-L86","documentation":"CanvasSurfaceHandle::surface lazily asks the wgpu instance to create a surface targeting the stored HTML canvas and panics when that fails. Surface creation fails when a GPU context cannot attach to the element: an existing incompatible context, a browser without WebGPU, or an instance that cannot present to canvases.","triggerScenarios":"The canvas already having a 2D context acquired elsewhere (context-type conflict); running in a browser without navigator.gpu; the canvas element being detached or garbage-collected by the time the surface is created.","commonSituations":"Safari or Firefox without WebGPU enabled; graphs with GPU nodes where the canvas is shared with 2D blitting; headless test browsers without GPU acceleration.","solutions":["Feature-detect WebGPU (navigator.gpu / successful adapter request) before the wgpu path and fall back to CPU rendering","Use a dedicated canvas for the wgpu surface and never call get_context(\"2d\") on it","Handle the Result from create_surface and log wgpu's error so the graph can degrade instead of panicking"],"exampleFix":"// before\nlet surface = executor.context().instance.create_surface(wgpu::SurfaceTarget::Canvas(canvas)).expect(\"Failed to create surface from canvas\");\n\n// after\nlet surface = executor.context().instance.create_surface(wgpu::SurfaceTarget::Canvas(canvas)).unwrap_or_else(|e| {\n\tpanic!(\"Failed to create surface from canvas: {e}\")\n});","handlingStrategy":"validation","validationCode":"// host page: only enable the wgpu path when WebGPU is present\n// if (!navigator.gpu) { /* stay on the CPU render path */ }","typeGuard":"fn webgpu_available() -> bool {\n\tjs_sys::Reflect::get(&js_sys::global(), &JsValue::from_str(\"gpu\"))\n\t\t.map(|v| !v.is_undefined())\n\t\t.unwrap_or(false)\n}","tryCatchPattern":"match instance.create_surface(wgpu::SurfaceTarget::Canvas(canvas)) {\n\tOk(surface) => surface,\n\tErr(e) => return Err(format!(\"wgpu surface creation failed: {e}\").into()),\n}","preventionTips":["Request a compatible adapter before building the executor in canvas environments","Keep wgpu-surface canvases and 2D canvases strictly separate","Retain a JS reference to surface canvases so they cannot be garbage-collected mid-frame"],"tags":["wgpu","canvas","webgpu","surface"],"backgroundTag":"wgpu-surface-creation-failed","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}