Summary
Electrobun 2.x's build-time Cottontail runtime intermittently SIGSEGVs at JSC bootstrap when spawned by Hutch during electrobun build / electrobun dev. The crash aborts before any config or bundling runs, so electrobun build --env=dev|stable and electrobun dev fail with CottontailBuildFailed. It is not project-specific and is not fixed by the newest beta pairing.
Environment
- macOS (darwin arm64), Apple Silicon
- Pairing A (stable):
electrobun@2.0.1↔hutch@0.24.3↔cottontail@0.5.0 - Pairing B (beta):
electrobun@2.0.2-beta.35↔hutch@0.27.0↔cottontail@0.7.0 - Both pairings reproduce. (Cottontail binaries run standalone;
cottontail --versionand a trivialcottontail build file.tsboth succeed.)
Repro
From any Hutch/Electrobun 2.x project:
./node_modules/.bin/electrobun build --env=dev
# or
./node_modules/.bin/electrobun dev
# or
bun run dev # electrobun dev --watchOutput:
cottontail: fatal runtime signal SIGSEGV
version: 0.5.0
platform: darwin arm64
error: CottontailBuildFailed
error: script "dev" exited with code 1No esbuild/TS/config diagnostic is emitted — it is a native crash, not a build error.
Minimal repro (no project work happens at all): hutch electrobun build --help also segfaults. That isolates it to Cottontail's bootstrap during Hutch invocation, below the JS config layer.
Frequency
Intermittent, and the rate is unstable across sessions:
- Earlier measurement on pairing A: ~2/12 fail (
PASS=10 FAIL=2), same tree. - Beta pairing B: ~1/6 fail.
- Most recent session: 9/9 fail (both
bun run devand bare./node_modules/.bin/electrobun dev).
Because it passes sometimes, it initially looked like dev worked while build didn't.
Crash signature
.ips reports (byProc: cottontail): EXC_BAD_ACCESS / SIGSEGV, subtype KERN_INVALID_ADDRESS, termination Segmentation fault: 11.
Faulting thread (representative, pairing A / cottontail 0.5.0):
__pthread_kill
pthread_kill
raise
cottontail uv_wtf8_to_utf16
cottontail std::__1::__call_once_proxy[abi:ne210100]<std::__1::tuple<void (&)()>>(void*)
cottontail vmEntryHostFunction
cottontail llintPCRangeStart
cottontail JSC::mapIteratorPrivateFuncMapIteratorValue(...)
cottontail JSC::iteratorHelperPrivateFuncCreate(...)
cottontail JSC::SyntheticModuleRecord::destroy(...)
cottontail JSC::WebAssemblyModuleRecord::destroy(...)The abort originates in Cottontail's JSC/VM bootstrap (raise() after a wild pointer), via a C++ std::call_once once-init, running JIT'd JS iterators. No esbuild / bundle-copy / config symbols appear anywhere in the stack. Pairing B reports show the same KERN_INVALID_ADDRESS abort with cottontail_jsc_get_class_definition_empty in the stack — the fault survives the 0.5.0 → 0.7.0 jump.
Disproven (worth not re-investigating)
- Stale per-PID state / locks — with all hutch processes killed and
.cottontail-tmp/,~/.hutch/state/locks/graph.lock, the project lock, and.hutch/locks/electrobun-build.lockall deleted, the next build still crashed identically. - Version mismatch —
hutch --version→ 0.24.3, correctly paired with cottontail 0.5.0 (reve5660061b8e64b5ea044799da8518780a9987391); the Electrobun release manifest declarescottontail.defaultVersion: "0.5.0". hutch sync/ upgrade /--env=stable— same toolchain, same crash.- Pristine checkout — reproduces from a clean tree.
- Project source —
hutch electrobun build --helpsegfaults, so no project code is involved.
Impact
Blocks electrobun build and any publish/CI step that runs it (prepack). The dev workaround we used is electrobun run against a previously built bundle, which depends on a prior successful build.
We worked around it for now by pinning electrobun@1.18.1 (no Hutch/Cottontail in the build path), so we're unblocked, but we can't adopt 2.x until this is fixed.
Ask
A fix in Cottontail's JSC bootstrap, or a Hutch/Cottontail pairing known to be stable. Happy to attach a full .ips or run any instrumented build to help narrow it.
- Crash reports on disk:
~/Library/Logs/DiagnosticReports/cottontail-*.ips(19+ reports, all the same faulting-thread signature)
Activity
2A second complete run on the same current supported pairing (Electrobun 2.0.2 / Hutch 0.27.1 / Cottontail 0.7.1, same binary hash as above) stopped after 50 passing stages. This time the standalone packaged runtime terminated with SIGSEGV 83 ms into unchanged tests/validation.test.ts, with no output. The schema stage that failed in the first run passed this time. Neither failed run is treated as green, and no automatic retries were added.
The command is the same as above with tests/validation.test.ts as the entry. No new system .ips was found for this second crash, so I cannot claim matching native frames. Second failed report retains the exact command, exit code, empty-output hash and all preceding stages; the first failed report is also retained.
Additional bounded diagnostics: 500 schema and 500 validation startup probes loaded the full original TypeScript test modules (adapter imports changed to absolute paths), then exited before test bodies or filesystem work; 1,000/1,000 passed. The original validation test also passed through a JavaScript entry wrapper that logs before importing it. Together with the earlier 200 adapter-import probes, this is 1,200 startup probe passes, without reproducing the native failure on demand. The complete native app/webview workflow passed separately on fresh disposable dictionaries.
Diagnostic evidence distinguishes these passes from full-gate readiness. No root cause, runtime fix or application data loss is established. This may be related to the bootstrap failure in this issue, but the shared cause is still unconfirmed.
Possibly related evidence from the current stable pairing: Electrobun 2.0.2, Hutch 0.27.1, packaged Cottontail 0.7.1, macOS 26.6.2 (25G83), arm64. Latest supported releases were rechecked before investigation.
This occurred in a standalone packaged runtime spawned by Python, rather than Hutch's build-time runtime. After 44 serial safety stages passed, starting our unchanged schema test entry terminated with SIGSEGV in 90 ms, with no test output. The full run remains failed; no automatic retry was added.
Invocation, from the repository root after packaging:
APPis the absolute path to the retained production app. The runtime reports0.7.1; SHA-256 is84428a0f30babd9a1aedfcb5b75b0027e6ea53cfd5153d80e593da745cc65822.The system crash report records:
EXC_BAD_ACCESS,SIGSEGV,KERN_INVALID_ADDRESS at 0x0000000000000010.86502F03-79C4-3EC2-BDB3-ED7C344F8460.0x271d488,0x271c75c,0x271a570,0x2719cb4,0x2713da0,0x21c2f8c,0x2751d8c,0x2736d7c.std::__1::__call_once_proxy[abi:ne210100]<std::__1::tuple<void (&)()>>(void*), with large offsets; these names alone do not establish the root cause.Explicit diagnostics afterward: the schema test passed both directly and through a JavaScript entry wrapper. 100 serial JavaScript-wrapper module-load probes and 100 direct TypeScript adapter-import probes also passed. We cannot reproduce the crash on demand and do not claim a runtime fix. No application data loss was observed. The failed gate, sanitized crash excerpt, commands and every probe outcome are retained locally.