SIGABRT on "HTTP Client" thread — abort() from BoringSSL crypto/bio/bio.cc (faultingThread=7)

Open 💬 0 comments Opened Jul 15, 2026 by lokkaflokka

SIGABRT on "HTTP Client" thread — abort() from BoringSSL crypto/bio/bio.cc (faultingThread=7)

Summary

Claude Code crashes with EXC_CRASH (SIGABRT) on the thread named "HTTP Client" (thread 7). Disassembly of the crashing frame points at a fatal abort() inside the bundled BoringSSL BIO layer (vendor/boringssl/crypto/bio/bio.cc), reached when a BIO buffer-length invariant fails. Reproduces offset-for-offset identically across 2.1.209 and 2.1.210.

Environment

  • All four crashes occurred on macOS 14.3.1 (23D60), arm64, under Claude Code 2.1.209 and 2.1.210.
  • The same machine was subsequently updated to macOS 26.5.2 (25F84); no recurrence since — but only a short amount of Claude Code runtime has accumulated on the new OS, so this is not confirmed fixed, just absent so far.
  • Bundled single-file executable (~230 MB, arm64), stripped (only __mh_execute_header retained).

Crash instances

All four are faultingThread=7, thread name "HTTP Client", EXC_CRASH / SIGABRT / Abort trap: 6:

| Version | Local time (EDT) |
|---|---|
| 2.1.209 | 2026-07-14 15:55:49 |
| 2.1.210 | 2026-07-15 06:40:37 |
| 2.1.210 | 2026-07-15 06:53:37 |
| 2.1.210 | 2026-07-15 07:28:02 |

Thread-7 backtrace (system frames symbolicated)

0  libsystem_kernel.dylib   __pthread_kill +8
1  libsystem_pthread.dylib  pthread_kill +288
2  libsystem_c.dylib        __abort +136
3  libsystem_c.dylib        abort +192
4  <cc-binary>  imageOffset 0x8E18FC   <- calls abort()
5  <cc-binary>  imageOffset 0x8DDAB8
6  <cc-binary>  imageOffset 0x8DDFC8
7  <cc-binary>  imageOffset 0x906988
8  <cc-binary>  imageOffset 0x760958
9  <cc-binary>  imageOffset 0x1455518
10 <cc-binary>  imageOffset 0x1447124
11 <cc-binary>  imageOffset 0x1444630
12 <cc-binary>  imageOffset 0x1444CF8
13 <cc-binary>  imageOffset 0x1D83150
14 libsystem_pthread.dylib  _pthread_start +136
15 libsystem_pthread.dylib  thread_start +8

The thread-7 in-binary offsets (frames 4–13) are byte-identical across 2.1.209 and 2.1.210:

0x8E18FC  0x8DDAB8  0x8DDFC8  0x906988  0x760958
0x1455518 0x1447124 0x1444630 0x1444CF8 0x1D83150

Same code path in both builds — not merely the same exception type. The offset stability across a version bump suggests the path lives in the vendored runtime/TLS layer rather than app JS.

What the disassembly established

Frame 4 return address is imageOffset 0x8E18FC; the preceding instruction is the call:

0x8E18F8:  bl   <stub 0x1032CF910>          ; return addr 0x8E18FC (this frame)
  • [certain] stub 0x1032CF910 resolves via the indirect symbol table (stub index 254) to _abort. So frame 4 is a direct abort() call — not __stack_chk_fail, not a trap.
  • [certain] The enclosing function's error paths load an embedded source-path string ../../vendor/boringssl/crypto/bio/bio.cc (adrp x3, …; add x3, #3458) and pass it, with what look like (lib, line) constants, to an internal error reporter — so the function is compiled from BoringSSL's crypto/bio/bio.cc.
  • [inferred from register/branch logic, not symbols] The bl _abort is a cold no-return block reached from two branches (b 0x8E18F8 and b.hi 0x8E18F8). The surrounding code invokes a BIO callback (blr x9), takes its returned length, and compares it against a 16-bit field in a BIO buffer struct (three uint16 fields at struct offsets 112/114/116 + a pointer at 104); it aborts when the returned length exceeds the buffer's tracked remaining count. Reads as BoringSSL treating a BIO buffer-length invariant violation as fatal (a BIO callback reporting more bytes than available) and calling abort() instead of returning an error.

Net: "HTTP Client" thread → BoringSSL bio.cc buffer-length invariant → abort() → SIGABRT.

Notes for whoever symbolicates

  • Frames 5–13 are unresolved (binary is stripped). A dSYM for this build would name them directly — they're the callers into the BIO routine (frames 5–8 in the same ~7–9 MB region; frames 9–13 in the ~21 MB and ~30 MB regions, likely the HTTP/TLS session code and the JS/runtime boundary). Start at frame 4 (0x8E18FC) in crypto/bio/bio.cc and walk up.
  • UUID caveat: the Mach-O LC_UUID is 4c4c4448-5555-3144-a11c-f75e90db7fe9 and is shared across 2.1.208, 2.1.209, and 2.1.210 (distinct binaries, different file sizes). It's a placeholder/synthetic linker UUID, not a content hash — so UUID cannot identify which build a report came from, and dSYM lookup keyed on UUID will be ambiguous. Match on the CFBundleShortVersionString / procName (2.1.209 vs 2.1.210) instead.

Ask

Low urgency — reporting for signal, not a live blocker (all instances predate an OS update; none since). If the abort site is cheap to check: please symbolicate frames 5–13 against the dSYM and confirm the BIO invariant reading, and flag whether a macOS 14.x TLS/network interaction is a known trigger for this BoringSSL BIO abort. Raw .ips for both versions available on request.

View original on GitHub ↗