GraphiteEditor/Graphite · error
ApplicationIo not available
Error message
ApplicationIo not available
What it means
The wgpu_executor node resolves the GPU executor from the scope-provided PlatformEditorApi and .expect("ApplicationIo not available") panics when application_io is None, i.e. the evaluation environment has no platform IO backend at all. It is the first of two assertions in this node; the second (line 306) additionally requires a GPU executor inside the ApplicationIo. The sibling try_wgpu_executor node in the same file returns Option and never panics, existing precisely for environments where these backends may be absent.
Source
Thrown at node-graph/nodes/gstd/src/platform_application_io.rs:304
/// The scope-provided editor API giving access to the platform's resource storage.
#[scope(editor_api::IDENTIFIER)]
editor_api: Item<&'a PlatformEditorApi>,
/// The content hash identifying which stored resource to load.
hash: Item<ResourceHash>,
) -> Item<Resource> {
let hash = hash.into_element();
let application_io = editor_api.into_element().application_io.as_ref().expect("ApplicationIo must be available when using resources");
let resource = application_io.load_resource(hash).await.unwrap_or_else(|| panic!("Resource {hash} not found"));
Item::new_from_element(resource)
}
#[node_macro::node(category(""), inject_scope)]
pub async fn wgpu_executor<'a: 'n>(_: impl Ctx, #[scope(editor_api::IDENTIFIER)] editor_api: Item<&'a PlatformEditorApi>) -> Item<&'a ::wgpu_executor::WgpuExecutor> {
let executor = editor_api
.into_element()
.application_io
.as_ref()
.expect("ApplicationIo not available")
.gpu_executor()
.expect("GPU executor not available");
Item::new_from_element(executor)
}
#[node_macro::node(category(""), inject_scope)]
pub async fn try_wgpu_executor<'a: 'n>(_: impl Ctx, #[scope(editor_api::IDENTIFIER)] editor_api: Item<&'a PlatformEditorApi>) -> Item<Option<&'a ::wgpu_executor::WgpuExecutor>> {
let executor = editor_api.into_element().application_io.as_ref().and_then(|application_io| application_io.gpu_executor());
Item::new_from_element(executor)
}
/// Uploads image data from CPU memory into a GPU texture so that GPU-based nodes can process it.
#[node_macro::node(category("Debug"), memoize)]
pub 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>> {
let executor = executor.into_element();
let (raster, attributes) = content.into_parts();
Item::from_parts(raster.convert(Footprint::DEFAULT, executor).await, attributes)View on GitHub (pinned to c507b35645)
Solutions
- Switch the graph to the try_wgpu_executor node (same file), which yields Item<Option<&WgpuExecutor>> and lets you branch to CPU processing instead of panicking
- Provide an ApplicationIo in the scope's editor_api entry so the platform stack is complete
- Evaluate inside the platform that constructed PlatformEditorApi with application_io set
- Propagate a proper evaluation error instead of .expect so hosts can report the missing backend
Example fix
// before: panics when the platform provides no IO
let executor = editor_api.into_element().application_io.as_ref().expect("ApplicationIo not available").gpu_executor()...;
// after: depend on the non-panicking variant and handle absence explicitly
let executor: Option<&WgpuExecutor> = try_wgpu_executor_result.into_element();
match executor {
Some(executor) => gpu_path(executor).await,
None => cpu_fallback_path().await,
} Defensive patterns
Strategy: fallback
Validate before calling
// Host-side: verify the platform IO backend exists before evaluating GPU-dependent graphs
let io_present = editor_api.application_io.is_some();
if !io_present {
// route the graph to CPU nodes / inform the user before evaluation Type guard
fn has_application_io(api: &PlatformEditorApi) -> bool {
api.application_io.is_some()
} Try / catch
let outcome = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| evaluate_gpu_graph(doc)));
if outcome.is_err() {
// fall back to CPU evaluation or surface a 'GPU backend unavailable' message
} Prevention
- Prefer the try_* (Option-returning) node variants whenever a backend may legitimately be absent
- Declare required platform services per graph and validate them at load time, not at evaluation time
- Sandbox graph evaluation so a missing-backend panic becomes a reportable node failure
When it happens
Trigger: Evaluating any graph that requests the wgpu_executor scope dependency (GPU raster nodes, upload_texture, render nodes) in an environment whose editor_api carries application_io = None: headless test hosts, CLI pipelines, or custom graph hosts that inject PlatformEditorApi without platform IO.
Common situations: Running GPU-dependent documents in CI; embedding the node graph in a custom application that forgot to provide platform IO; platform ports mid-development; tests that construct a minimal scope and then touch GPU nodes.
Related errors
- ApplicationIo must be available when using resources
- GPU executor not available
- GPU executor not available
- GPU executor not available
- GPU executor should be available when we receive a texture
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/abcdfd9c5346b455.
Report an issue: GitHub.