gfx-rs/wgpu · critical
Accessing the GPU is only supported on the main thread or fr
Error message
Accessing the GPU is only supported on the main thread or from a dedicated worker
What it means
ContextWebGpu::new panics when navigator.gpu (or the worker-equivalent) cannot be retrieved via get_browser_gpu_property. WebGPU is only accessible on the main thread or inside a dedicated Web Worker; shared workers, service workers, and non-browser environments have no GPU object. wgpu panics at instance creation because the whole backend is unusable without it.
Source
Thrown at wgpu/src/backend/webgpu.rs:1651
crate::cmp::impl_eq_ord_hash_proxy!(WebPipelineCache => .ident);
crate::cmp::impl_eq_ord_hash_proxy!(WebCommandEncoder => .ident);
crate::cmp::impl_eq_ord_hash_proxy!(WebComputePassEncoder => .ident);
crate::cmp::impl_eq_ord_hash_proxy!(WebRenderPassEncoder => .ident);
crate::cmp::impl_eq_ord_hash_proxy!(WebCommandBuffer => .ident);
crate::cmp::impl_eq_ord_hash_proxy!(WebRenderBundleEncoder => .ident);
crate::cmp::impl_eq_ord_hash_proxy!(WebRenderBundle => .ident);
crate::cmp::impl_eq_ord_hash_proxy!(WebSurface => .ident);
crate::cmp::impl_eq_ord_hash_proxy!(WebSurfaceOutputDetail => .ident);
crate::cmp::impl_eq_ord_hash_proxy!(WebQueueWriteBuffer => .ident);
crate::cmp::impl_eq_ord_hash_proxy!(WebBufferMappedRange => .ident);
impl dispatch::InstanceInterface for ContextWebGpu {
fn new(desc: crate::InstanceDescriptor) -> Self
where
Self: Sized,
{
let Ok(gpu) = get_browser_gpu_property() else {
panic!(
"Accessing the GPU is only supported on the main thread or from a dedicated worker"
);
};
ContextWebGpu {
gpu,
requested_backends: desc.backends,
ident: crate::cmp::Identifier::create(),
}
}
unsafe fn create_surface(
&self,
target: crate::SurfaceTargetUnsafe,
) -> Result<dispatch::DispatchSurface, crate::CreateSurfaceError> {
match target {
SurfaceTargetUnsafe::RawHandle {
raw_display_handle: _,View on GitHub (pinned to 3e11ff59bf)
Solutions
- Create the wgpu Instance on the main thread or in a DedicatedWorker and pass resources/handles as needed.
- Check 'gpu' in navigator (and window.isSecureContext) before instantiating and fall back to another backend or show a support message.
- Serve the app over HTTPS/localhost and use a browser with WebGPU enabled (Chrome 113+, Edge, recent Firefox/Safari).
Example fix
// before
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor::default()); // panics in service worker
// after (main thread)
if (!("gpu" in navigator) || !window.isSecureContext) { throw new Error("WebGPU unavailable"); }
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor::default()); Defensive patterns
Strategy: validation
Validate before calling
// run before creating an Instance on web
if js_sys::Reflect::get(&web_sys::window().unwrap().navigator(), &"gpu".into()).is_err() || !js_sys::eval("window.isSecureContext").unwrap().is_truthy() {
panic!("WebGPU unavailable: need main thread or dedicated worker, secure context, WebGPU-capable browser");
} Type guard
fn webgpu_available(navigator: &web_sys::Navigator) -> bool {
js_sys::Reflect::has(navigator.as_ref(), &"gpu".into()).unwrap_or(false)
} Prevention
- Create the wgpu Instance only on the main thread or in a DedicatedWorker.
- Serve over HTTPS or localhost (secure context required).
- Feature-detect navigator.gpu before any wgpu initialization and provide a fallback message/backend.
When it happens
Trigger: Calling wgpu::Instance::new (or creating a ContextWebGpu) from a shared worker or service worker, from a thread without navigator.gpu, or in an environment where navigator.gpu is undefined (no WebGPU support / insecure context).
Common situations: Running WASM code inside a Service Worker (e.g. offline processing); older browsers without WebGPU; serving over plain HTTP instead of HTTPS (WebGPU requires a secure context); creating the instance on a spawned non-dedicated worker thread.
Related errors
- Mismatched pop_error_scope call: no error scope for this thr
- Unexpected error: constructor={constructor} value={value}
- multi-plane textures are not supported
- Clamp to border is not supported
- expected valid handle for canvas
AI-assisted analysis of gfx-rs/wgpu@3e11ff59bf (2026-09-03).
Data as JSON: /api/errors/4551d824f49d6a92.
Report an issue: GitHub.