{"record":{"id":"65c691ef630b48f4","repo":"moeru-ai/airi","slug":"audiocontext-not-initialized","errorCode":null,"errorMessage":"AudioContext not initialized","messagePattern":"AudioContext not initialized","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/audio/src/audio-context/index.ts","lineNumber":148,"sourceCode":"    return context\n  }\n  catch (err) {\n    error = errorMessageFromValue(err)\n    isReady = false\n    workletLoaded = false\n    notifyListeners()\n    console.error('Failed to initialize AudioContext:', err)\n    throw err\n  }\n  finally {\n    isInitializing = false\n    notifyListeners()\n  }\n}\n\nexport function createAudioSource(mediaStream: MediaStream): MediaStreamAudioSourceNode {\n  if (!context || !isReady) {\n    throw new Error('AudioContext not initialized')\n  }\n\n  const source = context.createMediaStreamSource(mediaStream)\n  activeSources.add(source)\n  return source\n}\n\nexport function createAudioAnalyser(options?: Partial<{\n  fftSize: number\n  smoothingTimeConstant: number\n  minDecibels: number\n  maxDecibels: number\n}>): AnalyserNode {\n  if (!context || !isReady) {\n    throw new Error('AudioContext not initialized')\n  }\n\n  const analyser = context.createAnalyser()","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/packages/audio/src/audio-context/index.ts#L130-L166","documentation":"createAudioSource guards on `if (!context || !isReady)` and throws when the shared AudioContext has not been initialized (or its initialization has not completed). The module exposes initializeAudioContext() which must resolve and set isReady=true before any factory that builds source/analyser/gain nodes is called.","triggerScenarios":"Calling createAudioSource(mediaStream) before awaiting initializeAudioContext(); initializeAudioContext failed (e.g. worklet loading failed) so isReady stayed false; the context was closed/teared down elsewhere resetting state.","commonSituations":"Component mount race where a recorder starts before audio init resolves; calling audio factories during SSR or in a non-DOM environment; user gesture requirements not satisfied so the context stays suspended/unready.","solutions":["Await initializeAudioContext() at app startup (or inside a user gesture) before creating any audio nodes.","Track isReady via a listener/notifyListeners subscription and only create sources once ready.","Verify the call runs in a browser context with a usable AudioContext."],"exampleFix":"// before\nconst src = createAudioSource(stream) // may throw if not initialized\n\n// after\nawait initializeAudioContext()\n// optionally: await a ready promise / subscribe to notifyListeners\nconst src = createAudioSource(stream)","handlingStrategy":"validation","validationCode":"if (!context || !isReady) {\n  throw new Error('Call and await initializeAudioContext() before creating audio sources')\n}","typeGuard":"function isAudioReady(): boolean {\n  return !!context && isReady && context.state !== 'closed'\n}","tryCatchPattern":"try {\n  return createAudioSource(stream)\n}\ncatch (err) {\n  if (/not initialized/i.test((err as Error).message)) {\n    await initializeAudioContext()\n    return createAudioSource(stream)\n  }\n  throw err\n}","preventionTips":["Await initializeAudioContext() at app startup or inside the first user gesture.","Expose a ready promise/flag via notifyListeners and gate factory calls on it.","Never call audio factories during SSR."],"tags":["web-audio","lifecycle","initialization","ordering"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}