| name | webgpu-errors-debugging |
| description | Use when debugging WebGPU: diagnosing validation messages, surfacing WGSL compile errors, or capturing a GPU frame. Prevents the undebuggable-from-a-generic-message problem caused by unlabeled descriptors. Covers object labels, error scopes for isolation, getCompilationInfo and GPUCompilationMessage, debug groups and markers, and browser GPU tooling. Keywords: WebGPU debugging, label, getCompilationInfo, GPUCompilationMessage, shader compile error, debug group, insertDebugMarker, RenderDoc, chrome gpu, how do I debug WebGPU, where is my shader error.
|
| license | MIT |
| compatibility | Designed for Claude Code. Requires WebGPU 1.0-stable. |
| metadata | {"author":"OpenAEC-Foundation","version":"1.0"} |
WebGPU Debugging
Make WebGPU failures diagnosable: label every object, surface WGSL compile errors with
exact line and column, isolate failing operations with error scopes, and annotate the
command stream so GPU captures are readable. Applies to WebGPU 1.0-stable (Chrome 113+,
Safari 26+, Firefox 141+).
Quick Reference
| Tool | API or location | What it diagnoses |
|---|
| Object labels | label field on every descriptor | Which object a validation message refers to |
| Error scopes | device.pushErrorScope / device.popErrorScope | Which exact call produced an error |
| Shader compile info | shaderModule.getCompilationInfo() | WGSL syntax and type errors with line and column |
| Debug groups | encoder.pushDebugGroup / popDebugGroup | Hierarchy of work in a GPU capture |
| Debug markers | encoder.insertDebugMarker | A single named point in the command stream |
| Console | Chrome DevTools console | Uncaptured WebGPU errors at runtime |
chrome://gpu | Browser address bar | Adapter and driver status, blocklisting |
chrome://flags/#enable-unsafe-webgpu | Browser address bar | Enables experimental WebGPU features |
| GPU frame capture | RenderDoc, or PIX on Windows via Dawn | Full per-draw state of a captured frame |
Decision Tree
Symptom: a validation error mentions "a texture" / "a buffer" but you cannot tell which
-> Labels are missing. ALWAYS set a meaningful label on every descriptor.
Re-run; the message now quotes your label.
Symptom: createRenderPipeline / createComputePipeline fails with an opaque message
-> The WGSL has a compile error. Call shaderModule.getCompilationInfo() and read
messages where type === "error" for exact lineNum and linePos.
Symptom: an error fires but you do not know which call site caused it
-> Bracket the suspect block with pushErrorScope("validation") / popErrorScope().
See webgpu-errors-validation for filter selection.
Symptom: many errors fire at once after one bad object
-> Errors are contagious. Find the FIRST error: bracket each creation call
individually and fix the earliest failure, not the downstream noise.
Symptom: a GPU frame capture is an unreadable flat list of draw calls
-> Debug groups are missing. Wrap each pass or phase with
pushDebugGroup(name) / popDebugGroup().
Symptom: navigator.gpu is undefined or requestAdapter() returns null
-> Check chrome://gpu for adapter status and confirm a secure context (https or
localhost). See webgpu-core-architecture.
Core Patterns
Pattern 1: ALWAYS label every object
Every WebGPU descriptor accepts an optional label string. GPUError messages quote
these labels. ALWAYS set a descriptive label on every buffer, texture, sampler, pipeline,
bind group, bind group layout, shader module, and command encoder.
const depthTexture = device.createTexture({
label: "shadow-depth-texture",
size: [2048, 2048],
format: "depth32float",
usage: GPUTextureUsage.RENDER_ATTACHMENT,
});
A validation error then reads ... texture "shadow-depth-texture" ... instead of
... a texture .... NEVER ship descriptors without a label.
Pattern 2: ALWAYS check getCompilationInfo after createShaderModule
createShaderModule does not throw on a WGSL error. The error surfaces later, as an
opaque pipeline-creation failure. ALWAYS inspect compilation info immediately after
creating the module.
const module = device.createShaderModule({ label: "main-shader", code: wgsl });
const info = await module.getCompilationInfo();
for (const msg of info.messages) {
console[msg.type === "error" ? "error" : "warn"](
`${msg.type} at ${msg.lineNum}:${msg.linePos} - ${msg.message}`,
);
}
info.messages is an array of GPUCompilationMessage, each with type
("error" / "warning" / "info"), message, lineNum, linePos, offset, and
length. A type === "error" message means the module is invalid; NEVER build a
pipeline from it.
Pattern 3: ALWAYS bracket a suspect call with an error scope
To tie an error to one call site, push a validation error scope before the suspect
operation and pop it after. The promise from popErrorScope() resolves to the first
captured GPUError or null.
device.pushErrorScope("validation");
const pipeline = device.createRenderPipeline(pipelineDescriptor);
const error = await device.popErrorScope();
if (error) console.error("Pipeline invalid:", error.message);
See webgpu-errors-validation for the full error-scope and uncapturederror model.
Pattern 4: ALWAYS annotate the command stream with debug groups
pushDebugGroup / popDebugGroup and insertDebugMarker attach names to the command
stream. These names appear in GPU frame captures and turn a flat draw list into a
readable hierarchy. ALWAYS wrap each pass or rendering phase in a debug group.
encoder.pushDebugGroup("shadow-pass");
const shadowPass = encoder.beginRenderPass(shadowPassDescriptor);
shadowPass.end();
encoder.popDebugGroup();
Groups nest. Every pushDebugGroup MUST be matched by exactly one popDebugGroup on the
same encoder before finish(), or encoding fails validation.
Pattern 5: NEVER debug a downstream error first
WebGPU errors are contagious: an object built from an invalid descriptor is itself
invalid, and every later operation that consumes it also fails. ALWAYS find and fix the
FIRST reported error. Bracket each creation call with its own error scope to locate the
root cause instead of chasing the cascade.
Pattern 6: ALWAYS check chrome://gpu before deep debugging
When WebGPU is entirely unavailable, the problem is environmental, not code. chrome://gpu
reports adapter and driver status and whether WebGPU is blocklisted. WebGPU also requires
a secure context (https or localhost). Confirm the environment before instrumenting code.
Common Anti-Patterns
| Anti-pattern | Why it fails | Fix |
|---|
Shipping descriptors with no label | Validation messages can only say "a texture"; you cannot tell which one | Set a meaningful label on every descriptor |
Ignoring getCompilationInfo() after createShaderModule | WGSL errors never throw at module creation; they surface only as opaque pipeline-creation failures | Inspect compilationInfo.messages for type === "error" with lineNum and linePos |
| No debug groups around passes | GPU captures are an unreadable flat list with no phase boundaries | Wrap each pass with pushDebugGroup / popDebugGroup |
Critical Warnings
- NEVER ship a descriptor without a
label. Unlabeled objects make every validation
message a guessing game.
- NEVER build a pipeline from a shader module whose
getCompilationInfo() returned a
type === "error" message. The module is invalid and the pipeline will fail.
- NEVER assume
createShaderModule throws on a WGSL error. It does not. The only channel
for compile diagnostics is getCompilationInfo().
- NEVER chase the last error in a cascade. Errors are contagious; fix the FIRST one.
- NEVER leave a
pushDebugGroup unmatched. Every push MUST have exactly one
popDebugGroup on the same encoder before finish().
- NEVER treat
uncapturederror as a diagnosis tool. It is telemetry only; it cannot tie
an error to a call site. Use error scopes instead. See webgpu-errors-validation.
Reference Files
references/methods.md : label discipline, getCompilationInfo and
GPUCompilationMessage fields, debug groups and markers, browser GPU tooling.
references/examples.md : verified code for labeled descriptors, checking
compilation info, and debug groups.
references/anti-patterns.md : debugging mistakes with WHY-it-fails explanations.
Related skills: webgpu-errors-validation (error scopes and filters),
webgpu-errors-device-loss (device-loss diagnosis), webgpu-core-pipeline-architecture
(shader module and pipeline creation).