{"record":{"id":"741949077d946fd3","repo":"moeru-ai/airi","slug":"audiocontext-or-worklets-not-ready","errorCode":null,"errorMessage":"AudioContext or worklets not ready","messagePattern":"AudioContext or worklets not ready","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/audio/src/audio-context/index.ts","lineNumber":227,"sourceCode":"  if (context && context.state === 'running') {\n    await context.suspend()\n    notifyListeners()\n  }\n}\n\nexport async function resumeAudioContext() {\n  if (context && context.state === 'suspended') {\n    await context.resume()\n    notifyListeners()\n  }\n}\n\nexport function createResamplingWorkletNode(\n  inputNode: AudioNode,\n  options: WorkletOptions = {},\n): AudioWorkletNode {\n  if (!context || !isReady || !workletLoaded) {\n    throw new Error('AudioContext or worklets not ready')\n  }\n\n  const workletOptions = {\n    inputSampleRate: sampleRate,\n    outputSampleRate: 16000,\n    channels: 1,\n    converterType: 2, // SRC_SINC_MEDIUM_QUALITY\n    bufferSize: 4096,\n    ...options,\n  }\n\n  const workletNode = new AudioWorkletNode(context, 'resampling-processor', {\n    numberOfInputs: 1,\n    numberOfOutputs: 1,\n    channelCount: workletOptions.channels,\n    processorOptions: workletOptions,\n  })\n","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/audio/src/audio-context/index.ts#L209-L245","documentation":"createResamplingWorkletNode is stricter than the other factories: it needs the AudioContext ready AND workletLoaded true, because AudioWorkletNode(context, 'resampling-processor', ...) only works after both addModule calls in loadWorklets() succeeded. If either condition fails it throws this error.","triggerScenarios":"Calling createResamplingWorkletNode(inputNode) before initializeAudioContext() resolves (worklets load inside it), or after loadWorklets failed — the wrapped 'Worklet loading failed' error was caught upstream and this factory is still used.","commonSituations":"Speech/mic capture code creating a 16 kHz resampling pipe before the audio bootstrap completes; environments without AudioWorklet support; a previous worklet load failure (CSP, 404) left workletLoaded false while callers ignored the init error.","solutions":["Await initializeAudioContext() — it loads both worklet modules and sets workletLoaded — before creating resampling nodes","If init threw 'Worklet loading failed', fix that first (URL, MIME type, CSP); this error is the downstream symptom","Feature-detect AudioWorklet support and skip the resampling path where unavailable"],"exampleFix":"// before\nconst node = createResamplingWorkletNode(source) // Error: AudioContext or worklets not ready\n\n// after\nif (typeof AudioWorkletNode === 'undefined') throw new Error('AudioWorklet unsupported')\nawait initializeAudioContext(48000) // loads processor + libsamplerate worklets\nconst node = createResamplingWorkletNode(source)","handlingStrategy":"validation","validationCode":"if (typeof AudioWorkletNode === 'undefined')\n  throw new Error('AudioWorklet unsupported in this environment')\nawait initializeAudioContext(48000) // loads both worklet modules and sets workletLoaded\nconst node = createResamplingWorkletNode(source)","typeGuard":null,"tryCatchPattern":"try {\n  const node = createResamplingWorkletNode(source)\n}\ncatch (err) {\n  if (err instanceof Error && err.message === 'AudioContext or worklets not ready') {\n    await initializeAudioContext(48000) // retry the gate that sets workletLoaded\n    return createResamplingWorkletNode(source)\n  }\n  throw err\n}","preventionTips":["Treat initializeAudioContext as the only entry to worklet-based pipelines","Propagate worklet load failures instead of continuing to build nodes","Feature-detect AudioWorklet before offering resampling features"],"tags":["web-audio","audio-worklet","resampling","initialization"],"backgroundTag":"audiocontext-not-initialized","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}