{"record":{"id":"210878555b6e2330","repo":"GraphiteEditor/Graphite","slug":"gpu-executor-not-available","errorCode":null,"errorMessage":"GPU executor not available","messagePattern":"GPU executor not available","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"node-graph/nodes/gstd/src/platform_application_io.rs","lineNumber":306,"sourceCode":"\teditor_api: Item<&'a PlatformEditorApi>,\n\t/// The content hash identifying which stored resource to load.\n\thash: Item<ResourceHash>,\n) -> Item<Resource> {\n\tlet hash = hash.into_element();\n\tlet application_io = editor_api.into_element().application_io.as_ref().expect(\"ApplicationIo must be available when using resources\");\n\tlet resource = application_io.load_resource(hash).await.unwrap_or_else(|| panic!(\"Resource {hash} not found\"));\n\tItem::new_from_element(resource)\n}\n\n#[node_macro::node(category(\"\"), inject_scope)]\npub async fn wgpu_executor<'a: 'n>(_: impl Ctx, #[scope(editor_api::IDENTIFIER)] editor_api: Item<&'a PlatformEditorApi>) -> Item<&'a ::wgpu_executor::WgpuExecutor> {\n\tlet executor = editor_api\n\t\t.into_element()\n\t\t.application_io\n\t\t.as_ref()\n\t\t.expect(\"ApplicationIo not available\")\n\t\t.gpu_executor()\n\t\t.expect(\"GPU executor not available\");\n\tItem::new_from_element(executor)\n}\n\n#[node_macro::node(category(\"\"), inject_scope)]\npub async fn try_wgpu_executor<'a: 'n>(_: impl Ctx, #[scope(editor_api::IDENTIFIER)] editor_api: Item<&'a PlatformEditorApi>) -> Item<Option<&'a ::wgpu_executor::WgpuExecutor>> {\n\tlet executor = editor_api.into_element().application_io.as_ref().and_then(|application_io| application_io.gpu_executor());\n\tItem::new_from_element(executor)\n}\n\n/// Uploads image data from CPU memory into a GPU texture so that GPU-based nodes can process it.\n#[node_macro::node(category(\"Debug\"), memoize)]\npub async fn upload_texture<'a: 'n>(_: impl Ctx, content: Item<Raster<CPU>>, #[scope(wgpu_executor::IDENTIFIER)] executor: Item<&'a ::wgpu_executor::WgpuExecutor>) -> Item<Raster<GPU>> {\n\tlet executor = executor.into_element();\n\tlet (raster, attributes) = content.into_parts();\n\n\tItem::from_parts(raster.convert(Footprint::DEFAULT, executor).await, attributes)\n}\n","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/node-graph/nodes/gstd/src/platform_application_io.rs#L288-L324","documentation":"The second assertion in the wgpu_executor node: application_io exists but its gpu_executor() returned None, so the platform IO backend has no GPU executor attached, and .expect(\"GPU executor not available\") panics. This happens when GPU initialization never succeeded (wgpu adapter/device request failed, e.g. no suitable adapter or WebGPU unavailable) or on platforms whose ApplicationIo deliberately ships without GPU support. try_wgpu_executor handles this case without panicking.","triggerScenarios":"Requesting the GPU executor scope dependency on a machine/browser where the wgpu adapter request failed (no Vulkan/Metal/DX12/WebGPU), where device creation was blocked by driver blacklist or policy, or where the platform's ApplicationIo variant does not construct a GPU executor at all.","commonSituations":"Browsers with WebGPU disabled or unsupported; VMs and remote-desktop sessions without GPU passthrough; CI runners without GPUs; systems whose drivers fail wgpu device creation; stale GPU drivers.","solutions":["Use the try_wgpu_executor node to obtain Option<&WgpuExecutor> and route to CPU fallback nodes when it is None","Fix GPU initialization: enable WebGPU in the browser, install/update GPU drivers, or run against a software adapter (lavapipe/LLVMpipe)","Inspect startup logs from adapter/device creation to see why no GPU executor was attached to ApplicationIo","Replace .expect with error propagation so the graph reports a missing GPU backend as a node error"],"exampleFix":"// before\nlet executor = editor_api.into_element().application_io.as_ref().expect(\"ApplicationIo not available\").gpu_executor().expect(\"GPU executor not available\");\n\n// after: use the non-panicking sibling node and degrade explicitly\nlet executor: Option<&WgpuExecutor> = try_wgpu_executor(...).await.into_element();\nmatch executor {\n    Some(executor) => gpu_path(executor).await,\n    None => cpu_fallback_path().await,\n}","handlingStrategy":"fallback","validationCode":"let has_gpu = editor_api\n    .application_io\n    .as_ref()\n    .and_then(|io| io.gpu_executor())\n    .is_some();\nif !has_gpu {\n    // route the graph to CPU nodes / show a 'GPU unavailable' notice before evaluation\n}","typeGuard":"fn has_gpu_executor(api: &PlatformEditorApi) -> bool {\n    api.application_io.as_ref().and_then(|io| io.gpu_executor()).is_some()\n}","tryCatchPattern":"let outcome = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| evaluate_gpu_graph(doc)));\nif outcome.is_err() {\n    // GPU backend missing: fall back to CPU node graph or report to the user\n}","preventionTips":["Feature-detect the GPU executor at application startup (try_wgpu_executor returns Option) and remember the result","In browsers, verify WebGPU availability (navigator.gpu) before enabling GPU-dependent graphs","Maintain CPU-node equivalents for GPU-only operations so absence degrades instead of panicking","On desktop, fall back to a software adapter (lavapipe/LLVMpipe) when hardware adapter requests fail"],"tags":["rust","graphite","node-graph","wgpu","gpu-adapter","panic"],"backgroundTag":"gpu-adapter-unavailable","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}