moeru-ai/airi · error

AudioContext not initialized

Error message

AudioContext not initialized

What it means

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.

Source

Thrown at packages/audio/src/audio-context/index.ts:148

    return context
  }
  catch (err) {
    error = errorMessageFromValue(err)
    isReady = false
    workletLoaded = false
    notifyListeners()
    console.error('Failed to initialize AudioContext:', err)
    throw err
  }
  finally {
    isInitializing = false
    notifyListeners()
  }
}

export function createAudioSource(mediaStream: MediaStream): MediaStreamAudioSourceNode {
  if (!context || !isReady) {
    throw new Error('AudioContext not initialized')
  }

  const source = context.createMediaStreamSource(mediaStream)
  activeSources.add(source)
  return source
}

export function createAudioAnalyser(options?: Partial<{
  fftSize: number
  smoothingTimeConstant: number
  minDecibels: number
  maxDecibels: number
}>): AnalyserNode {
  if (!context || !isReady) {
    throw new Error('AudioContext not initialized')
  }

  const analyser = context.createAnalyser()

View on GitHub (pinned to 27111382b4)

Solutions

  1. Await initializeAudioContext() at app startup (or inside a user gesture) before creating any audio nodes.
  2. Track isReady via a listener/notifyListeners subscription and only create sources once ready.
  3. Verify the call runs in a browser context with a usable AudioContext.

Example fix

// before
const src = createAudioSource(stream) // may throw if not initialized

// after
await initializeAudioContext()
// optionally: await a ready promise / subscribe to notifyListeners
const src = createAudioSource(stream)
Defensive patterns

Strategy: validation

Validate before calling

if (!context || !isReady) {
  throw new Error('Call and await initializeAudioContext() before creating audio sources')
}

Type guard

function isAudioReady(): boolean {
  return !!context && isReady && context.state !== 'closed'
}

Try / catch

try {
  return createAudioSource(stream)
}
catch (err) {
  if (/not initialized/i.test((err as Error).message)) {
    await initializeAudioContext()
    return createAudioSource(stream)
  }
  throw err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12). Data as JSON: /api/errors/65c691ef630b48f4. Report an issue: GitHub.