Skip to content

opencode Worker subprocess crashes with SIGILL (illegal instruction) on Intel i5-7200U (Kaby Lake), freezing the system #36280

Closed as not planned

Description

@oovaa

Summary

The opencode CLI crashes with a SIGILL (illegal/invalid CPU instruction) in a Worker subprocess during normal use. The crash then triggers a recursive crash-handler cascade (systemd-coredump → drkonqi → apport) that exhausts memory (a handler tried to allocate ~28 GB) and ends with systemd (PID 1) taking an ABRT and freezing the whole machine, requiring a forced power-cycle.

Environment

  • opencode version: 1.17.18 (opencode --version works, exits 0 — the SIGILL is NOT at process startup, it's a Worker subprocess)
  • Binary: /home/omar/.opencode/bin/opencode, ELF64 x86-64, 188,979,328 bytes, built 2026-07-09 20:19 (one day before the crash). "not stripped".
  • OS: Ubuntu, kernel 7.0.0-27-generic codex-mini, openai responses api #27-Ubuntu SMP PREEMPT_DYNAMIC
  • CPU: Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz (Kaby Lake, 2016)
  • CPU feature flags present: sse sse2 ssse3 sse4_1 sse4_2 avx avx2 bmi1 bmi2 fma vmx
  • CPU feature flags ABSENT (relevant): no avx512*, no vaes, no avxvnni, no vpclmulqdq, no gfni — i.e. this is a pre-AVX-512 / pre-VAES core.
  • Kernel cmdline note: mitigations=off is set (relevant if any mitigation-gated path is involved).

Crash evidence (journalctl, boot before the freeze)

Primary crash — the actual root cause:

Jul 10 09:05:20 flex5 kernel: traps: Worker[10724] trap invalid opcode ip:2607064 sp:7fe0e4824bd0 error:0 in opencode[21a3064,24c8000+36e6000]
Jul 10 09:05:20 flex5 systemd-coredump[10727]: Process 10712 (opencode) of user 1000 terminated abnormally with signal 4/ILL, processing...

Secondary crash (collateral):

Jul 10 09:05:34 flex5 systemd-coredump[10755]: Process 10738 (brave) of user 1000 terminated abnormally with signal 5/TRAP, processing...

The recursive crash-handler cascade that killed the system:

09:05:34  (sd-parse-elf)     SEGV   in ld-linux-x86-64.so.2
09:05:34  drkonqi-coredump   ABRT   "free(): invalid pointer"
09:05:35  systemd-coredum     SEGV   in ld-linux-x86-64.so.2
09:05:35  drkonqi-coredum     OOM    __vm_enough_memory: comm: drkonqi-coredum, bytes: 28295184384 (tried to allocate ~28 GB)
09:05:35  apport              GPF    general protection fault in python3.14
09:05:35  systemd[1]          Caught <ABRT>, from our own process.  →  Freezing execution.   <-- hard freeze

coredumpctl shows the cores were not saved (RLIMIT_CORE is set to 1, aborting core → COREFILE missing), so no opencode core is available.

What we need from maintainers

  1. Identify the code path in the Worker subprocess that emits an illegal instruction on this CPU. Since --version works but a worker dies with SIGILL, this looks like a runtime-selected optimized routine (e.g. an AES/VAES, AVX-512, or other SIMD code path) being executed on a CPU that lacks the required feature — a CPU-feature-detection bug or a binary built targeting a higher GOAMD64/micro-arch level than Kaby Lake supports.
  2. The binary is 188 MB and "not stripped" — please also confirm the official Linux x86-64 release build's minimum micro-architecture baseline. If it assumes AVX-512/VAES, that breaks all pre-Skylake-X / Kaby Lake-and-older users.
  3. Separately: the crash-handler recursion + 28 GB allocation that freezes systemd is a robustness problem independent of the opencode bug. Any unhandled subprocess SIGILL should not be able to take down PID 1.

Reproduction

  • Hardware: Intel i5-7200U (Kaby Lake), no AVX-512/VAES.
  • Run opencode normally (the Worker subprocess crashes during operation; exact trigger not isolated yet, but it occurred during a normal session on 2026-07-10 ~09:05).
  • opencode --version → 1.17.18, exits 0 (so it's not a startup-time SIGILL).

Suggested next steps for triage

  • Please share the GOAMD64 level and any assembly/SIMD dependencies used by the worker (native libs, WASM runtime, bundled binaries).
  • A dmeso/objdump of the faulting PC (ip:2607064 within opencode) would pinpoint the exact illegal opcode if a maintainer can map it.

Activity

  1. github-actions commented on Jul 10, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

  2. oovaa commented on Jul 10, 2026

    @oovaa
    Author

    this happens all the time with peak cpu usage in the TUI

  3. oovaa commented on Jul 10, 2026

    @oovaa
    Author

    @thdxr check this bro

  4. oovaa commented on Jul 13, 2026

    @oovaa
    Author

    Update — root cause is NOT a missing CPU feature (SIGILL = Go runtime.abort/throw)

    I dug into the live crashes and the saved core dumps. The "illegal instruction from a too-new micro-arch (AVX-512 / VAES)" theory does not hold up. Here's the evidence:

    1. The faulting instruction is a deliberate UD2, at a constant PC

    From coredumpctl gdb on today's crash (PID 51531, opencode CLI, SIGILL):

    Program terminated with signal SIGILL, Illegal instruction.
    #0  0x0000000002607064 in ?? ()
    => 0x2607064:  ud2
       0x2607066:  int3
       0x2607067:  int3   ... (run of int3) ...
       0x2607070:  push %rbp      <-- next function prologue
    

    objdump of /home/omar/.opencode/bin/opencode at 0x2607064 shows ud2 followed by a long int3 pad — this is literally runtime.abort in Go (the function is UD2 + INT3 padding). info/bt is empty because abort has already torn the stack down (return addr zeroed).

    Critically, the faulting PC is the same every time:

    • Jul 10 original crash: kernel: traps: Worker[10724] trap invalid opcode ip:2607064 ...
    • Today's crashes: kernel: traps: opencode[54566] trap invalid opcode ip:2607064 ...

    A real #UD from an unsupported AVX-512/VAES instruction would fault at that SIMD instruction's address, which varies by code path. It would never be a fixed ud2 at 0x2607064 across every crash. So this is not a binary built for a higher GOAMD64 level.

    2. Therefore the SIGILL is a Go fatal panic (runtime.throw() → runtime.abort())

    throw("...") prints fatal error: <msg> to stderr, then executes UD2 to terminate. The constant ud2 PC means opencode's worker is hitting a runtime.throw() — most commonly a data race (concurrent map read and map write), a fatal error, or a stack overflow — independently of CPU micro-architecture. The "only breaks on older Intel" pattern in the linked duplicates is therefore likely incidental (common workload/environment trigger), not a SIMD baseline problem.

    3. How a maintainer can get the exact panic string

    The throw message is printed to stderr before the ud2. Cores are now being saved (COREFILE present, e.g. PID 51531 = 42.1M), so:

    • coredumpctl gdb <pid> then bt — though the abort frame hides the caller, OR
    • most reliable: run a crashing worker under gdb and break runtime.throw, then bt — the real caller (and the panic message) is visible there, before the stack is destroyed.

    4. The "freezing the whole machine" symptom is the crash-handler cascade, not the throw

    Regardless of the opencode bug, an unhandled subprocess SIGILL should not be able to take down PID 1. That's the recursive systemd-coredump → drkonqi → apport allocating ~28 GB. Worth fixing separately.

    5. Mitigations that stop the freeze (won't fix the throw)

    A drop-in already caps coredump memory (MemoryMax=512M, set Jul 10). Adding a CPU cap stops the coredump spin:

    sudo mkdir -p /etc/systemd/system/systemd-coredump@.service.d
    echo '[Service]
    CPUQuota=30%' | sudo tee -a /etc/systemd/system/systemd-coredump@.service.d/limits.conf
    

    Note: during the storm, opencode itself was also pegged at ~97–100% CPU (two opencode processes), so the throw/crash loop — not just coredump — is the CPU hog. Brave's separate SIGILL is Chromium's own crashpad and should not be conflated with the opencode worker bug.

    Summary

    • ❌ Not a CPU-feature / AVX-512 / VAES / GOAMD64 baseline issue.
    • ✅ A Go runtime.throw() fatal panic in the worker, visible as a constant UD2 at 0x2607064 (runtime.abort).
    • 🔎 Need the throw message: please break on runtime.throw against a saved core / live worker.
  5. washburnello commented on Sep 3, 2026

    @washburnello

    Hitting this exact crash — same instruction pointer offset (opencode+0x2407064 / absolute 0x2607064) in a "Worker" thread, SIGILL/ILL_ILLOPN.

    • CPU: AMD Ryzen 5 3600 (Zen 2) — has AVX2, but no AVX-512, VAES, or GFNI
    • OS: Omarchy (Arch Linux), kernel 7.1.9-arch1-2
    • opencode versions affected: 1.18.25 (3 crashes within ~90s) and 1.18.26 (recurred after updating — same address)
    • Reproduced running opencode --auto
    • Ruled out: no OOM, no memory pressure, no correlated system errors at crash time

    Rolling back to an older version as a workaround; happy to share the full coredumpctl backtrace or test a patched build if that'd help narrow down the offending code path.

  6. thdxr commented on Oct 11, 2026

    @thdxr
    Member

    Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.

    — from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions