Skip to content

[Bug]: iOS Voice Wake can crash reinstalling mic tap after Talk or screen recording #99093

Description

@PollyBot13

Bug type

Crash (process/app exits or hangs)

Beta release blocker

No

Summary

On iOS, OpenClaw can crash with an uncaught AVFoundation exception when Voice Wake restarts recognition and installs its input-node tap while Talk / native WebRTC or other external microphone capture is active or has just ended.

Steps to reproduce

Observed during physical iPhone proof testing of Talk with Voice Wake enabled:

  1. Install/run the iOS app on a physical iPhone.
  2. Enable Voice Wake.
  3. Start and stop Talk using native OpenAI WebRTC, including attempts where iOS screen recording with microphone was being tried.
  4. Observe intermittent app crashes during the testing sequence.

The exact minimal reproduction sequence is not fully isolated yet. The crash logs consistently show Voice Wake restarting from Talk/external-capture resume paths and failing while installing the AVAudioEngine input tap.

Expected behavior

Voice Wake should stay paused while Talk or another external audio capture owns the microphone, and resuming Voice Wake should not crash the app if the audio session/input format is temporarily unavailable or contended.

At worst, Voice Wake should fail closed with a recoverable status such as paused/start failed, then retry later.

Actual behavior

Three fresh foreground crashes were captured from the same physical iPhone test build. All are EXC_CRASH / SIGABRT / Abort trap: 6 from an uncaught AVFoundation exception while VoiceWakeManager.startRecognition() calls AVAudioNode.installTap(...).

The three restart paths seen in lastExceptionBacktrace were:

2026-07-02 15:14:50 +0200
VoiceWakeManager.startRecognition()
VoiceWakeManager.start()
closure #1 in VoiceWakeManager.resumeAfterExternalAudioCapture(wasSuspended:)
2026-07-02 15:16:01 +0200
AVAudioIONodeImpl::SetOutputFormat(...)
AUGraphNodeBaseV3::CreateRecordingTap(...)
AVAudioEngineImpl::InstallTapOnNode(...)
-[AVAudioNode installTapOnBus:bufferSize:format:block:]
VoiceWakeManager.startRecognition()
VoiceWakeManager.start()
closure #1 in VoiceWakeManager.setSuppressedByTalk(_:)
2026-07-02 15:19:42 +0200
AVAudioIONodeImpl::SetOutputFormat(...)
AUGraphNodeBaseV3::CreateRecordingTap(...)
AVAudioEngineImpl::InstallTapOnNode(...)
-[AVAudioNode installTapOnBus:bufferSize:format:block:]
VoiceWakeManager.startRecognition()
VoiceWakeManager.start()
closure #1 in VoiceWakeManager.handleRecognitionCallback(transcript:segments:errorText:)

The app-container Talk log around the same window shows direct OpenAI WebRTC sessions successfully starting and completing audio/transcript events, so this does not look like the native WebRTC route itself crashing. The crash appears to be Voice Wake re-acquiring microphone capture at the wrong time or without enough guard/retry around installTap.

OpenClaw version

2026.6.11, iOS build 128

Operating system

iPhone OS 18.7.9 (22H355)

Install method

Local physical-device iOS debug/proof build installed with xcrun devicectl device install app

Model

gpt-realtime-2 / OpenAI Realtime voice path was under test for Talk; the crash itself occurs in the local iOS Voice Wake speech-recognition path.

Provider / routing chain

iOS app Talk -> native OpenAI WebRTC via gateway-minted client secret; Voice Wake -> local iOS Speech / AVAudioEngine microphone capture.

Additional provider/model setup details

The successful Talk sessions in the app log used OpenAI Realtime WebRTC. Voice Wake was enabled during testing. The user was also trying iOS screen recording with microphone, and reported weird audio results; exact per-crash correlation with screen recording is not captured, but it is a plausible additional competing microphone-capture condition.

Logs

App: OpenClaw
Bundle ID: ai.openclawfoundation.app.test.pollybot-5y97h9j837
Version/build: 2026.6.11 / 128
OS: iPhone OS 18.7.9 (22H355)

Incident 107822BD-DFA1-478F-B677-B2836B302E24
Timestamp: 2026-07-02 15:14:50 +0200
Exception: EXC_CRASH / SIGABRT
Termination: Abort trap: 6
lastExceptionBacktrace includes:
  AVAudioEngineImpl::InstallTapOnNode(...)
  -[AVAudioNode installTapOnBus:bufferSize:format:block:]
  VoiceWakeManager.startRecognition()
  VoiceWakeManager.start()
  VoiceWakeManager.resumeAfterExternalAudioCapture(wasSuspended:)

Incident 76D9AC06-2931-4284-887D-48B9BC9D1BBC
Timestamp: 2026-07-02 15:16:01 +0200
Exception: EXC_CRASH / SIGABRT
Termination: Abort trap: 6
lastExceptionBacktrace includes:
  AVAudioIONodeImpl::SetOutputFormat(...)
  AUGraphNodeBaseV3::CreateRecordingTap(...)
  AVAudioEngineImpl::InstallTapOnNode(...)
  -[AVAudioNode installTapOnBus:bufferSize:format:block:]
  VoiceWakeManager.startRecognition()
  VoiceWakeManager.start()
  VoiceWakeManager.setSuppressedByTalk(_:)

Incident 4D0173CA-F702-46B6-AA3A-C0BF621798FE
Timestamp: 2026-07-02 15:19:42 +0200
Exception: EXC_CRASH / SIGABRT
Termination: Abort trap: 6
lastExceptionBacktrace includes:
  AVAudioIONodeImpl::SetOutputFormat(...)
  AUGraphNodeBaseV3::CreateRecordingTap(...)
  AVAudioEngineImpl::InstallTapOnNode(...)
  -[AVAudioNode installTapOnBus:bufferSize:format:block:]
  VoiceWakeManager.startRecognition()
  VoiceWakeManager.start()
  VoiceWakeManager.handleRecognitionCallback(transcript:segments:errorText:)

Screenshots, recordings, and evidence

Physical iPhone Talk proof video for the adjacent native-WebRTC testing is available in PR #98563. The crash logs above were pulled from the same device after the attempts that included failed/weird iOS screen-recording-with-microphone tests.

Impact and severity

Affected: iOS users who have Voice Wake enabled and use Talk or another microphone-capturing feature.

Severity: Crash. This can terminate the app during voice/Talk workflows.

Frequency: 3 fresh crashes observed during one physical iPhone test session; exact minimal repro not isolated.

Consequence: Talk/Voice testing is interrupted, and users may avoid Voice Wake as a workaround.

Additional information

Likely fix area:

  • apps/ios/Sources/Voice/VoiceWakeManager.swift
  • VoiceWakeManager.startRecognition() currently removes then installs an input-node tap immediately after configureAudioSession().
  • Restart entry points include setSuppressedByTalk(false), resumeAfterExternalAudioCapture(wasSuspended:), and recognition error restart.
  • NodeAppModel.setTalkEnabled(false) calls both setSuppressedByTalk(false) and resumeAfterExternalAudioCapture(wasSuspended:), so it is worth checking for duplicate/overlapping restart tasks after Talk ends.

Suggested hardening direction:

  • Serialize Voice Wake restart attempts so only one start() / startRecognition() pipeline can run at a time.
  • Add a short debounce after Talk/external capture ends before re-installing the Voice Wake tap.
  • Re-check suppression/audio-capture state immediately before installTap.
  • Treat AVAudioEngine tap installation failure as recoverable state, not an uncaught app crash.
  • Add focused tests around duplicate resume paths and Voice Wake remaining paused while Talk/external capture is active.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority user-facing bug, regression, or broken workflow.clawsweeper:needs-live-reproClawSweeper needs live local, crabbox, or manual validation to confirm this issue.impact:crash-loopCrash, hang, restart loop, or process-level availability failure.issue-rating: 🐚 platinum hermitGood issue quality with a plausible reproduction path needing some confirmation.maturity:stableIssue affects a taxonomy feature currently scored M4/M5.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions