iOfficeAI/AionUi · warning · AudioWorkletUnavailableError
AudioWorkletUnavailableError
Error message
AudioWorkletUnavailableError
What it means
`createPcmRecorder` needs the Web Audio `AudioWorklet` API to capture PCM frames; on browsers/electron builds where `context.audioWorklet` is undefined it closes the AudioContext, releases the mic stream, and throws `AudioWorkletUnavailableError`. This is a feature-detection failure, not a runtime crash.
Source
Thrown at packages/desktop/src/renderer/services/speech/pcmRecorder.ts:162
}): Promise<PcmRecorderHandle> => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const releaseMic = () => stream.getTracks().forEach((track) => track.stop());
// Request 24kHz directly; Chromium honors it, but some platforms ignore the
// hint, so the actual context.sampleRate is checked below.
let context: AudioContext;
try {
context = new AudioContext({ sampleRate: STREAM_SAMPLE_RATE });
} catch (error) {
releaseMic();
throw error;
}
const closeContext = (): Promise<void> => context.close().catch((): void => undefined);
if (!context.audioWorklet) {
await closeContext();
releaseMic();
throw new AudioWorkletUnavailableError();
}
const workletUrl = URL.createObjectURL(new Blob([WORKLET_SOURCE], { type: 'application/javascript' }));
try {
await context.audioWorklet.addModule(workletUrl);
} catch (error) {
await closeContext();
releaseMic();
throw error;
} finally {
URL.revokeObjectURL(workletUrl);
}
const contextRate = context.sampleRate;
const needsResample = contextRate !== STREAM_SAMPLE_RATE;
// Input samples (at context rate) needed to produce one 200ms output chunk.
const chunkInputSamples = Math.max(1, Math.round((STREAM_CHUNK_SAMPLES * contextRate) / STREAM_SAMPLE_RATE));
View on GitHub (pinned to 711aa0550e)
Solutions
- Upgrade the Electron/Chromium runtime to a version supporting AudioWorklet (Chrome 66+/Electron 3+)
- Feature-detect before starting capture and fall back to a non-worklet recorder (ScriptProcessorNode) or disable PCM speech features
- Verify the page is not running in a restricted context that strips WebAudio features
- In tests, mock AudioContext with an audioWorklet stub instead of exercising the real path
Example fix
// before
if (!context.audioWorklet) {
await closeContext();
releaseMic();
throw new AudioWorkletUnavailableError();
}
// after (pre-check and show guidance)
if (!('audioWorklet' in new AudioContext())) {
showToast(t('speech.pcmUnsupported')); // and skip the record button
} Defensive patterns
Strategy: type-guard
Validate before calling
const ctx = new AudioContext();
if (!('audioWorklet' in ctx)) { ctx.close(); /* fall back or disable PCM UI */ } Type guard
const supportsAudioWorklet = (): boolean => typeof AudioContext !== 'undefined' && 'audioWorklet' in AudioContext.prototype;
Try / catch
catch (e) { if (e instanceof AudioWorkletUnavailableError) disablePcmFeatures(); else throw e; } Prevention
- Feature-detect AudioWorklet before showing the record button
- Keep Electron/Chromium updated; stub audioWorklet in jsdom tests
When it happens
Trigger: Creating the PCM recorder in an environment whose AudioContext lacks the `audioWorklet` property — older Chromium/Electron versions (pre-Chrome 66), non-secure/non-standard embedding contexts, or environments with the WebAudio API partially polyfilled/stripped.
Common situations: Running the app on an old Electron/Chromium runtime; audio capture in an iframe or webview without proper feature support; test environments (jsdom) lacking real WebAudio; browser-polyfill conflicts removing audioWorklet.
AI-assisted analysis of iOfficeAI/AionUi@711aa0550e (2026-08-28).
Data as JSON: /api/errors/2037e7ae67f1c379.
Report an issue: GitHub.