Motion GPU normalizes all runtime errors into a consistent MotionGPUErrorReport structure. This page covers the error pipeline, classification patterns, default/custom error UI behavior, shader compile diagnostics, device loss handling, and retry strategy.
All adapters (Svelte, React, Vue) use the same runtime error contracts and MotionGPUErrorReport structure.
Error normalization pipeline
All errors from initialization and per-frame rendering are processed by toMotionGPUErrorReport(error, phase):
The function inspects the error message, classifies it into a stable category code, and produces a structured report.
MotionGPUErrorReport shape
This interface describes the runtime callback payload shape used by onError / errorRenderer.
Built-in classification patterns
The normalizer matches error messages against known patterns and assigns code, severity, recoverability, title, and hint:
Overlay behavior
By default, FragCanvas displays runtime errors through the adapter overlay component (MotionGPUErrorOverlay rendered via adapter portal utility):
Key behaviors
- Even when
showErrorOverlayisfalse,onErroris still called. - With
errorRendererset andshowErrorOverlay=true, custom UI is rendered instead of the default overlay. - Default overlay always surfaces report metadata (
phase,code,severity,recoverable) to make classification visible without opening details. - When shader diagnostics include runtime context, overlay includes a Runtime context section (
materialSignature, pass graph summary, active render targets). - When
errorHistoryLimit <= 0, history collection is disabled andonErrorHistoryreceives[]after resets. - When
errorHistoryLimit > 0, history behaves as a ring buffer containing only the latestNunique reports. - Consecutive identical reports (
phase/title/message/rawMessage) are deduplicated and do not append history. - The default overlay renders above canvas content using a DOM portal.
- Multiple errors display the most recent one.
Minimal error handling
<FragCanvas
{material}
onError={(report) => {
console.error(
`[${report.code}] (${report.severity}) [${report.phase}] ${report.title}: ${report.message}`
);
if (report.hint) console.info(`Hint: ${report.hint}`);
}}
showErrorOverlay={false}
/>Error history callbacks
<FragCanvas
{material}
errorHistoryLimit={10}
onErrorHistory={(history) => {
const latest = history[history.length - 1];
if (!latest) return;
console.info(`Recent errors: ${history.length}, latest code: ${latest.code}`);
}}
/>Custom error renderer
{#snippet myErrorRenderer(report)}
<aside class="error-banner">
<strong>{report.title}</strong>
<p>{report.message}</p>
</aside>
{/snippet}
<FragCanvas
{material}
errorRenderer={myErrorRenderer}
onError={(report) => {
console.error(report);
}}
/>Shader compile diagnostics
When WGSL compilation fails, the renderer extracts diagnostics from GPUShaderModule.getCompilationInfo() and maps line numbers using the material’s source line map.
Source location mapping
The line map tracks which generated WGSL line corresponds to which original source:
Structured diagnostics payload
For WGSL compilation failures, the error carries a structured diagnostics payload:
toMotionGPUErrorReport uses this to build:
message— first compiler error enriched with source label and generated-line context (when available).details— additional compiler messages with the same contextual labels.source— component location, line number, and highlighted code snippet.context— runtime snapshot (materialSignature, pass graph, active render targets) when provided by diagnostics payload.
For compute-stage failures, diagnostics payload carries shaderStage: 'compute' and computeSource; source mapping points to compute lines instead of fragment/include/define locations.
Because compute pipeline validation is partly asynchronous in WebGPU, a bad compute shader may first build an optimistic pending pipeline entry and then resolve to a structured compilation error after getCompilationInfo() / validation-scope results arrive. In that case the renderer schedules another render pass and surfaces the cached COMPUTE_COMPILATION_FAILED report on the next frame instead of falling back to derivative uncaptured-error noise.
Overlay Source panel
When report.source is available, the overlay shows:
- Active source tab: source label + location metadata (fragment/include/define/compute), with optional column.
- Source snippet centred around the failing line
- Highlighted failing line
- Additional diagnostics in a collapsible section
Device loss and uncaptured errors
The renderer listens for two asynchronous error conditions:
Once captured, the error state is stored. The next render call throws a normalized error so FragCanvas can display it through the standard reporting path.
For uncaptured errors, the renderer aggregates and normalizes messages before throwing:
- Tracks up to the most recent
12uncaptured messages and ignores immediate duplicates. - Prioritizes a non-derivative root-cause validation message as primary (instead of follow-up
Invalid CommandBuffernoise). - Includes additional unique uncaptured messages in the same thrown error payload under an
Additional uncaptured WebGPU errors (...)block.
Retry strategy
When renderer creation fails, FragCanvas retries with exponential backoff:
Retry state resets when the pipeline signature changes (e.g., when you fix a shader error and hot-reload).
Production recommendations
- Always provide
onError— send reports to your logging/telemetry system. - Keep default overlay enabled in dev/staging — it surfaces WGSL errors with line-level precision.
- Use
errorRendererin production when you need branded/error-system-integrated UI. - Route alerts by
code+severityfirst, then displayphaseandtitlefor triage context. - Enable bounded history (
errorHistoryLimit) for session diagnostics without unbounded memory growth. - Use
hintfor contextual guidance — each error classification provides a specific suggestion.