moeru-ai/airi · warning
[WhisperAdapter] ${deviceLossCount} device-loss events recor
Error message
[WhisperAdapter] ${deviceLossCount} device-loss events recorded, promoting load from webgpu to wasm. What it means
WhisperAdapter.load() checks the shared device-loss counter; when deviceLossCount >= DEVICE_LOSS_WASM_THRESHOLD it requests 'wasm' instead of the usual 'webgpu' and warns about the promotion. Rationale mirrors kokoro.ts: after repeated WebGPU device-loss events on this device, webgpu is treated as persistently unreliable and the adapter proactively falls back to the slower-but-stable wasm backend.
Source
Thrown at packages/stage-ui/src/libs/inference/adapters/whisper.ts:310
w.postMessage({ type: 'cancel', requestId: createRequestId(), targetRequestId: requestId })
const reason = signal.reason
reject(reason instanceof Error ? reason : new InferenceAbortError(typeof reason === 'string' ? reason : undefined))
}
signal.addEventListener('abort', abortListener)
}
})
}
async function load(
onProgress?: (p: ProgressPayload) => void,
options?: { signal?: AbortSignal },
): Promise<void> {
// NOTICE: Proactive WASM promotion after repeated device-loss events.
// See kokoro.ts for rationale. Whisper always requests 'webgpu' from the
// caller today, so we only check the promotion threshold.
const requestedDevice = deviceLossCount >= DEVICE_LOSS_WASM_THRESHOLD ? 'wasm' : 'webgpu'
if (requestedDevice === 'wasm') {
console.warn(
`[WhisperAdapter] ${deviceLossCount} device-loss events recorded, `
+ `promoting load from webgpu to wasm.`,
)
}
throwIfAborted(options?.signal)
return operationMutex.runExclusive(async () => {
throwIfAborted(options?.signal)
state = 'loading'
updateInferenceStatus(MODEL_NAMES.WHISPER, { state: 'downloading', device: requestedDevice as any })
return getLoadQueue().enqueue(MODEL_NAMES.WHISPER, LOAD_PRIORITY.ASR, async () => {
throwIfAborted(options?.signal)
const w = ensureWorker()
const requestId = createRequestId()
const readyPromise = waitForMessage(w, requestId, 'model-ready', LOAD_TIMEOUT, (data) => {
if (data.type === 'progress' && onProgress) {
const payload = data.payloadView on GitHub (pinned to 677329427f)
Solutions
- Accept the wasm fallback for ASR (latency rises, correctness unchanged).
- Update browser/drivers to reduce device-loss frequency so the threshold is never reached.
- If reproducible on your hardware, file the device-loss pattern against the browser's WebGPU tracker.
- To avoid the warn in kiosks, pre-select wasm for whisper on known-bad devices.
Defensive patterns
Strategy: fallback
Validate before calling
const requested = adapterHasDeviceLosses(deviceLossCount) ? 'wasm' : 'webgpu'
Prevention
- Share the device-loss counter concept across adapters so one model's crashes protect the others.
- Surface backend selection in diagnostics UI so users understand the speed change.
- Test the wasm path for whisper regularly, since promotion can silently engage.
When it happens
Trigger: Whisper load following one or more WebGPU device-loss events earlier in the session (possibly from another model's run); drivers/browsers with flaky WebGPU compute for conv nets.
Common situations: Same-machine sessions where kokoro already lost the device; hybrid-GPU laptops; long-running sessions after a driver reset.
Related errors
- [KokoroAdapter] ${deviceLossCount} device-loss events record
- [Whisper Worker] fp16 encoder failed, falling back to fp32:
- [WhisperAdapter] Restarting in ${delay}ms (attempt ${restart
- [Whisper Worker] WebGPU not available, falling back to WASM
- Invalid VRAM override: ${bytes} (expected null or non-negati
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/b9a57b10500bb7bd.
Report an issue: GitHub.