moeru-ai/airi · warning

Web Speech API recognition did not start immediately. This m

Error message

Web Speech API recognition did not start immediately. This might be due to:

What it means

First line of a multi-line console.warn block in the browser Web Speech API transcription provider. startRecognition() wraps recognition.start() and returns false when the call throws - most often an InvalidStateError (already started) or a permission/security failure. The provider deliberately does not retry: the SpeechRecognition instance stays created so a later start can succeed once microphone permission or a user gesture is available.

Source

Thrown at packages/stage-ui/src/libs/providers/providers/browser-web-speech-api/provider.ts:457

  }

  recognition.onsoundend = () => {
    console.info('Web Speech API sound ended')
  }

  recognition.onaudioend = () => {
    console.info('Web Speech API audio capture ended')
  }

  recognition.onnomatch = () => {
    console.info('Web Speech API: No speech match')
  }

  const started = startRecognition()
  if (!started) {
    // If immediate start failed, it might be a permission issue
    // Web Speech API will prompt for permission automatically, so we just log
    console.warn('Web Speech API recognition did not start immediately. This might be due to:')
    console.warn('1. Microphone permission not granted - browser should prompt automatically')
    console.warn('2. Recognition already running - this is normal if called multiple times')
    console.warn('3. Browser requires user gesture - ensure microphone was enabled by user action')

    // Don't retry immediately - wait for permission or user action
    // The recognition instance is already created, so it can be started later if needed
  }

  return {
    fullStream,
    text: deferredText.promise,
    textStream,
    recognition: recognitionInstance,
  }
}

View on GitHub (pinned to 677329427f)

Solutions

  1. Check the site's microphone permission and grant it, then trigger recognition again
  2. Start recognition from a user interaction (button click) on first enable so gesture requirements are satisfied
  3. Track running state via onstart/onend to avoid calling start() on an active recognition (InvalidStateError)
  4. Confirm window.SpeechRecognition or window.webkitSpeechRecognition exists before selecting this provider (Firefox lacks it)
  5. In Electron, allow 'media' via session.setPermissionRequestHandler so the renderer can use the API

Example fix

// before: recognition started automatically on mount
startRecognition()

// after: gate the first start behind a user gesture, tolerate double start
button.onclick = () => {
  try {
    recognition.start()
  }
  catch {
    // InvalidStateError: recognition already running - safe to ignore
  }
}
Defensive patterns

Strategy: validation

Validate before calling

const SR = window.SpeechRecognition ?? window.webkitSpeechRecognition
if (!SR)
  throw new Error('SpeechRecognition is not supported in this browser')
const perm = await navigator.permissions?.query({ name: 'microphone' as PermissionName })
if (perm && perm.state === 'denied')
  throw new Error('Microphone permission denied')

Type guard

function isSpeechRecognitionSupported(): boolean {
  return typeof window !== 'undefined'
    && Boolean(window.SpeechRecognition ?? window.webkitSpeechRecognition)
}

Try / catch

recognition.onerror = (event) => {
  if (event.error === 'not-allowed' || event.error === 'service-not-allowed')
    promptForMicrophonePermission()
}
try {
  recognition.start()
}
catch {
  // InvalidStateError: already running - safe to ignore
}

Prevention

When it happens

Trigger: Calling the provider's transcription entry while a SpeechRecognition instance is already running (double start), starting without microphone permission granted, starting outside a user gesture in browsers that require one, or running in a browser without window.SpeechRecognition / window.webkitSpeechRecognition. startRecognition() returns false and this warn block prints.

Common situations: First-run microphone prompt still pending; permission previously denied; Electron renderer without a user-gesture context; Chrome's speech service wedged after many restarts; iOS Safari gesture restrictions.

Related errors


AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18). Data as JSON: /api/errors/60297f6d8393403e. Report an issue: GitHub.