Skip to content

[iOS 26] EXC_BREAKPOINT (SIGTRAP) in HybridCameraPhotoOutput.capturePhoto at line 167 when calling output.capturePhoto(with:delegate:) #3916

@qutrek

Description

@qutrek

What's happening?

On iOS 26.4.2, calling photoOutput.capturePhoto(...) from JS reliably aborts the app with EXC_BREAKPOINT (SIGTRAP) brk 1 — a Swift runtime trap — inside HybridCameraPhotoOutput.capturePhoto(settings:callbacks:) at HybridCameraPhotoOutput.swift:167:

// 3. Perform capture
output.capturePhoto(with: captureSettings, delegate: delegate)

The do { try settings.toAVCapturePhotoSettings(...) ... } catch { ... } block on lines 162–172 doesn't catch it — the trap is Swift's brk 1 (try! / precondition / force-unwrap / fatalError), not a Swift Error. The settings construction on line 164 succeeded (no catch path entered); the trap fires on the next instruction.

+1104 byte offset from the function start, source-line attribution = HybridCameraPhotoOutput.swift:167.

Stack ends in RCTJSThreadManager runRunLoop — i.e., the JS thread is the one driving the call (HybridFunction::callMethodHybridCameraPhotoOutputSpecSwift::capturePhoto → Swift). Photo capture is initiated from JS via the public photoOutput.capturePhoto(...) API; no out-of-band thread is involved.

The app cannot wrap this in try/catch (JS) or do/catch (Swift) — by the time control could return, the process is already terminated by the kernel.

Suspect

Lines 65–70 of the same file are the only iOS-26-conditional block in the photo-output path:

if #available(iOS 26, *),
   output.isCameraSensorOrientationCompensationSupported
{
  output.isCameraSensorOrientationCompensationEnabled = false
}

This runs in init before any capture. It is the only iOS-26-specific configuration applied to the AVCapturePhotoOutput. Possible interaction with the settings produced by toAVCapturePhotoSettings on iOS 26 — worth ruling in/out.

Reproduceable Code

Camera configured with usePhotoOutput and useVideoOutput, both wired into <Camera outputs={outputs} />:

const PHOTO_OUTPUT_OPTIONS = {
  targetResolution: CommonResolutions.UHD_4_3,
  qualityPrioritization: 'quality',
  quality: 0.95,
} as const;

const photoOutput = usePhotoOutput(PHOTO_OUTPUT_OPTIONS);

// On photo-mode mount, pre-warm flash variants (documented perf pattern):
useEffect(() => {
  if (mode !== 'photo') return;
  photoOutput
    .prepareSettings([
      { flashMode: 'off', enableShutterSound: false },
      { flashMode: 'on',  enableShutterSound: false },
      { flashMode: 'auto', enableShutterSound: false },
    ])
    .catch(err => /* log */);
}, [mode, photoOutput]);

// Shutter tap:
const photo = await photoOutput.capturePhoto(
  {
    flashMode: 'off',           // or 'on' / 'auto'
    enableShutterSound: false,
    location: captureLocation,  // optional { latitude, longitude, ... }
  },
  {},
);

Vanilla usage — no custom settings beyond what's documented.

Relevant log output

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x0000000105c4b028
Termination Reason: SIGNAL 5 Trace/BPT trap: 5
Triggered by Thread:  4   (RCTJSThreadManager — JS thread)

Thread 4 Crashed:
0   App     HybridCameraPhotoOutput.capturePhoto(settings:callbacks:) + 1104   (HybridCameraPhotoOutput.swift:167)
1   App     protocol witness for HybridCameraPhotoOutputSpec_protocol.capturePhoto(settings:callbacks:) in conformance HybridCameraPhotoOutput + 20
2   App     HybridCameraPhotoOutputSpec_cxx.capturePhoto(settings:callbacks:) + 88   (HybridCameraPhotoOutputSpec_cxx.swift:145)
3   App     margelo::nitro::camera::HybridCameraPhotoOutputSpecSwift::capturePhoto(...) + 64   (HybridCameraPhotoOutputSpecSwift.hpp:104)
4   App     facebook::jsi::Value margelo::nitro::HybridFunction::callMethod<...> + 176   (HybridFunction.hpp:179)
5   App     margelo::nitro::HybridFunction::createHybridFunction<...> + 280   (HybridFunction.hpp:119)
6-10  hermesvm   HermesRuntimeImpl::HFContext::func → NativeFunction::_nativeCall → Interpreter::handleCallSlowPath → interpretFunction
11-13 hermesvm   JSFunction::_callImpl → Callable::executeCall2 → generatorPrototypeResume
14-19 hermesvm   …interpretFunction → JSFunction::_callImpl → Callable::executeCall3 → arrayPrototypeForEach
20+   hermesvm   …interpretFunction → HermesRuntimeImpl::call
+   App      facebook::react::UIManagerBinding::dispatchEventToJS
+   App      facebook::react::Scheduler → EventQueueProcessor::flushEvents → RuntimeScheduler_Modern::runEventLoop
+   App      RCTMessageThread::runAsync → __CFRunLoopDoBlocks → CFRunLoopRunSpecific
+   App      +[RCTJSThreadManager runRunLoop] + 204   (RCTJSThreadManager.mm:102)

Thread State at trap:

pc: 0x0000000105c4b028   (== `HybridCameraPhotoOutput.capturePhoto + 1104`)
esr: 0xf2000001 (Breakpoint) brk 1

The brk 1 ESR confirms this is the Swift runtime trap instruction, not a memory fault.

Camera Device

Back camera, no special configuration beyond targetResolution: UHD_4_3 + qualityPrioritization: 'quality'. Format auto-selected by RNVC. HDR off at time of capture.

Device

iPad 10th gen (iPad13,18), iOS 26.4.2 (23E261).

A related but distinct crash signature in the same HybridCameraPhotoOutput / CapturePhotoDelegate module also reproduces on iPhone 11 Pro (iPhone12,1) / iOS 18.7.8 (22H352) — different stack (delegate callback during _handlePreparationCompleteNotificationWithPayload while a session start is in flight on another thread). Filed separately as #3917.

VisionCamera Version

5.0.10

Can you reproduce this issue in the VisionCamera Example app?

Not yet tested against the bare example app — the user-side trigger is a normal shutter tap in our app's photo-capture screen, which has reproduced on a TestFlight build (iOS 26.4.2 / iPad 10), but I don't have a repro count from a single device session. Happy to attempt a minimal repro in the example app if the suspect lines (65–70) don't immediately point you somewhere.

Additional information

  • iOS
  • Android
  • Using New Architecture (Fabric / TurboModules)
  • Hermes
  • Expo SDK 56 (RN 0.85.3, React 19.2, Reanimated v4)
  • Nitro Modules

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions