stablyai/orca · error

Failed to start microphone recording

Error message

Failed to start microphone recording

What it means

Thrown by startMobileDictationDesktopSession when options.commitRecordingStart() returned false. commitRecordingStart (provided by use-mobile-dictation.ts) returns false when the native toggleRecording(true) call did not succeed — i.e., the device-level microphone recording could not actually start. The surrounding catch rolls back any partial native audio state and cancels the remote session.

Source

Thrown at mobile/src/hooks/mobile-dictation-desktop-start.ts:118

    keepAwakeOwner
      .acquire(dictationId)
      .catch((err: unknown) => console.error('Keep-awake activation failed', err))
      .finally(() => {
        clearTimeout(budgetTimer)
        resolve()
      })
  })

  if (!isCurrentStart(options)) {
    await cancelStaleStart(options, { releaseKeepAwake: true })
    return false
  }

  try {
    // Commit in the same continuation as the final stale check; returning first
    // would let a queued cancel resurrect microphone recording after cleanup.
    if (!options.commitRecordingStart()) {
      throw new Error('Failed to start microphone recording')
    }
  } catch (err) {
    const wasCurrent = isCurrentStart(options)
    // Native recording can partially start before throwing, so stop audio before
    // releasing the wake tag and remote session.
    try {
      options.rollbackRecordingStart()
    } catch {
      // Continue releasing independently owned resources after native audio failure.
    }
    options.clearActiveId(dictationId)
    await Promise.allSettled([
      keepAwakeOwner.release(dictationId),
      client.sendRequest('speech.dictation.cancel', { dictationId })
    ])
    const shouldReport = wasCurrent && canReportStartFailure(options)
    setIdleIfGenerationCurrent(options)
    if (!shouldReport) {

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Guarantee tearDown() / toggleRecording(false) ran before attempting a new start — call cancel() to fully reset native audio first.
  2. Confirm no other app is using the microphone (have the user close other audio apps).
  3. Verify the native module @orca/expo-two-way-audio is linked and its audio session category is configured for record-only on iOS.
  4. If commitRecordingStart keeps returning false on a device, file a native-audio bug with the recorder's error log.

Example fix

// before — startMobileDictationDesktopSession
if (!options.commitRecordingStart()) {
  throw new Error('Failed to start microphone recording')
}

// after — capture the native recorder's reason so the UI can guide the user
const reason = options.lastRecordingStartFailure?.() 
if (!options.commitRecordingStart()) {
  throw new Error(reason ? `Failed to start microphone recording: ${reason}` : 'Failed to start microphone recording')
}
Defensive patterns

Strategy: validation

Validate before calling

// Ensure native audio is in a clean state before committing start
await tearDown()
const initialized = await initialize()
if (!initialized) throw new Error('Native audio failed to initialize')

Type guard

function isMicrophoneStartError(err: unknown): boolean {
  return err instanceof Error && err.message === 'Failed to start microphone recording'
}

Try / catch

try {
  return await startMobileDictationDesktopSession(options)
} catch (err) {
  if (isMicrophoneStartError(err)) {
    showError('Microphone unavailable. Close other audio apps and try again.')
    return false
  }
  throw err
}

Prevention

When it happens

Trigger: options.commitRecordingStart() returns false. In use-mobile-dictation.ts this happens when toggleRecording(true) (from @orca/expo-two-way-audio) returns false: the native audio module refused to start capture. Causes: another app holds the mic, the audio session category is wrong, the native module threw and was caught, hardware mic unavailable.

Common situations: Another app (Calls, Voice Memos) is holding the microphone on iOS; Android audio focus was denied; the native audio module was not initialized (initialize() returned true but the recorder still failed); a previous session left the recorder in a bad state.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/7be3cbb00ff21a9e. Report an issue: GitHub.