Skip to content

EXC_BAD_ACCESS in Room.publisherShouldNegotiate / Room.fullConnectSequence on every connect (2.14.0 + 2.14.1, macOS arm64) #1036

@utkarsh-socratic

Description

@utkarsh-socratic

SDK version: client-sdk-swift 2.14.0 and 2.14.1 (both reproducible)
Platform: macOS 26.5 (Tahoe), arm64
App: menubar SwiftUI client embedding LiveKit via a thin wrapper SDK

Symptom

Every connect to a Room crashes with EXC_BAD_ACCESS within ~5–8 s of Room.connect(...). Two distinct stacks observed in the same SDK version, both deep inside Room:

Stack A — on first SDP offer

SignalClient._process(signalResponse:)
 → Room.signalClient(_:didReceiveOffer:offerId:)
 → Room.publisherShouldNegotiate(force:)
 → direct field offset for Room._regionManager
 → EXC_BAD_ACCESS (KERN_INVALID_ADDRESS at 0x28)

Stack B — during initial connect sequence

Room.fullConnectSequence(_:_:)
 → @objc closure #1 in Room.fullConnectSequence(_:_:)
 → EXC_BAD_ACCESS (KERN_INVALID_ADDRESS at 0x20)

The crashing thread in stack A is the main thread doing a SwiftUI layout pass; the corrupting work is on a webrtc dispatch thread (webrtc::Thread::ProcessMessages → PhysicalSocketServer::WaitPoll) that the Room delegate hop returns into.

Memory corruption, not a null deref

Bad-access addresses differ across reproductions: 0x28, 0x10001002a, 0x7a326d303934685d (ASCII garbage, looks like a stomped value), 0x20. Same SDK version, same call site. That pattern points at a use-after-free of a Room-owned object (likely _regionManager, which appears as a direct field offset for symbol in stack A) rather than a static null pointer.

What rules out our deployment

Reproduced identically against three independent LiveKit servers:

  1. LiveKit Cloud (production environment)
  2. LiveKit Cloud (staging environment)
  3. Self-hosted livekit-server via the project's own dev docker-compose, fronted by a local realtime worker registering against ws://localhost:7880

Same SDK version, same call stack, same 0x28 subtype on stack A regardless of which server is on the other end. Server-side ICE/TURN/SFU is therefore not the variable.

Reproducibility

100% — five .ips files from a single afternoon, every voice session attempted ended this way. The connect path always reaches Room.publisherShouldNegotiate (stack A) or dies during fullConnectSequence (stack B); there is no successful session on this build.

Tried

  • 2.14.1 → crash (stack A consistently)
  • 2.14.0 → crash (stack A primarily, stack B once)
  • 2.13.0 → could not test; SDK removed LiveKitSDK.setTracing(_:) and the Span(label:) initializer used by our ConnectTracing, so it does not compile against our codebase without source changes.

Happy to share .ips files privately if useful — they contain workspace IDs / user identifiers that I'd rather not paste in a public issue.

Environment

  • SwiftPM, Swift 6 language mode
  • LiveKit dependency surface used: Room.connect(...), ConnectOptions(enableMicrophone: true) (publish-during-join), Room.prepareConnection for prewarm, LiveKitSDK.setLogLevel, LiveKitSDK.setTracing
  • Transitive: livekit-uniffi-xcframework 0.0.6, webrtc-xcframework 144.7559.6

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions