Skip to content

Opencode segfaults in NixOS+WSL #26846

Closed as not planned
Closed as not planned

Description

@muckelba

Description

I'm not able to run opencode inside of WSL running NixOS:

Unstable:

nix run nixpkgs/nixos-unstable#opencode -- --version
zsh: segmentation fault  nix run nixpkgs/nixos-unstable#opencode -- --version

Dev:

nix run github:anomalyco/opencode
error: Cannot build '/nix/store/hpl0fz47xs1bs9qfggv2g0v9yzrcbx2v-opencode-1.14.46+a780186.drv'.
       Reason: builder failed with exit code 1.
       Output paths:
         /nix/store/nrsbqjxmr2f2jpvjq6ly9vi7nzvjarjv-opencode-1.14.46+a780186
       Last 25 log lines:
       > dist/assets/angular-ts-BwZT4LLn.js                          183.87 kB │ gzip:  16.73 kB │ map:   249.42 kB
       > dist/assets/vue-vine-8moa0y9V.js                            190.27 kB │ gzip:  18.16 kB │ map:   255.24 kB
       > dist/assets/wolfram-lXgVvXCa.js                             262.44 kB │ gzip:  77.10 kB │ map:   279.68 kB
       > dist/assets/session-CLdkD14I.js                             528.86 kB │ gzip: 174.86 kB │ map: 1,979.63 kB
       > dist/assets/wasm-CG6Dc4jp.js                                622.38 kB │ gzip: 231.20 kB │ map:   622.93 kB
       > dist/assets/cpp-CofmeUqb.js                                 626.12 kB │ gzip:  44.93 kB │ map:   816.15 kB
       > dist/assets/ghostty-web-CmRTNB3y.js                         652.83 kB │ gzip: 188.67 kB │ map:   793.29 kB
       > dist/assets/emacs-lisp-C9XAeP06.js                          779.90 kB │ gzip: 196.57 kB │ map:   789.84 kB
       > dist/assets/index-BtCt3uoZ.js                             1,787.77 kB │ gzip: 512.18 kB │ map: 7,132.59 kB
       >
       > (!) Some chunks are larger than 500 kB after minification. Consider:
       > - Using dynamic import() to code-split the application
       > - Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/configuration-options/#output-manualchunks
       > - Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.
       > ✓ built in 12.13s
       > building opencode-linux-x64
       > Running smoke test: dist/opencode-linux-x64/bin/opencode --version
       > Smoke test failed for opencode-linux-x64: ShellError: Failed with exit code 139
       >  exitCode: 139,
       >    stdout: "",
       >    stderr: "",
       >
       >       at ShellPromise (unknown:75:16)
       >       at BunShell (unknown:191:35)
       >
       For full logs, run:
         nix log /nix/store/hpl0fz47xs1bs9qfggv2g0v9yzrcbx2v-opencode-1.14.46+a780186.drv

(exit code 139 is segfault)

Stable is working tho:

nix run nixpkgs/nixos-25.11#opencode -- --version
1.1.14

Also using the non-nixos version from the https://opencode.ai/install script works fine

How can i debug this?

WSL:

uname -r
6.6.87.2-microsoft-standard-WSL2

Nix:

nix --version
nix (Nix) 2.34.7

NixOS:

nixos-version
26.05.20260505.549bd84 (Yarara)

Plugins

No response

OpenCode version

No response

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

NixOS 26.05

Terminal

Windows Terminal

Activity

  1. yipengsun commented on May 11, 2026

    @yipengsun

    I'm having the same issue on NixOS + WSL.

  2. janczarn commented on May 11, 2026

    @janczarn

    I can also confirm this issue on NixOS in WSL.

  3. fjararibet commented on May 12, 2026

    @fjararibet

    It's been happening for a while, I didn't catch it was a wsl issue. Version 1.4.3 is the latest one I got to work.

    nix run github:anomalyco/opencode/877be7e8e -- --version
    1.4.3+877be7e
    
  4. added a commit that references this issue on May 13, 2026
  5. mikebirdgeneau commented on May 13, 2026

    @mikebirdgeneau

    I just confirmed that v1.14.25 works for me narrowing down to between after v1.14.25 (working) and before v1.14.31 (failing)

  6. alex-bartleynees commented on Jun 6, 2026

    @alex-bartleynees

    I'm having the same issue with opencode on nixos-wsl too, works fine on my nixos desktop, some issue with the wsl kernel maybe?

  7. OdysseusOperator commented on Jun 10, 2026

    @OdysseusOperator

    Rolled back to 1.14.30, which works. So it is definetly something since version 1.14.31 acording to @alex-bartleynees post.

    Just a simple opencode --version is enough for me to check if it is crashing.

  8. sonowz commented on Jun 17, 2026

    @sonowz

    Looks like this is an issue of nixpkgs (or bun): NixOS/nixpkgs#520383

    By the way I managed to create a workaround for segfault:

    # 1. Copy the broken binary to a writeable area
    cp $(which .opencode-wrapped) /tmp/opencode-fixed
    chmod +w /tmp/opencode-fixed
    
    # 2. Force patchelf to rewrite the interpreter cleanly
    nix-shell -p patchelf --run "patchelf --set-interpreter \$(patchelf --print-interpreter /tmp/opencode-fixed) /tmp/opencode-fixed"
    
    
    # 3. Test if the repaired binary runs
    /tmp/opencode-fixed --version

    copy the /tmp/opencode-fixed binary somewhere to store it

  9. yuzow commented on Aug 3, 2026

    @yuzow

    I hit this on NixOS+WSL2 and tracked down the root cause. Note Opus helped me debug this so take that as you will. It's an ELF layout problem in the built binary, and the WSL2 kernel is stricter about it than mainline.

    opencode --version
    1.18.4

    uname -r
    6.6.87.2-microsoft-standard-WSL2

    nix --version
    nix (Nix) 2.34.8

    nixos-version
    26.11.20260729.0954f7e (Zokor)

    Root cause

    The crash is in ld.so, before any opencode code runs:

    .opencode-wrapp[1737907]: segfault at 6510e40 ip 00007603d54370e8 error 6
      in ld-linux-x86-64.so.2
    
    SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x6510e40}
    

    That address is not arbitrary. It's a copy relocation target:

    $ readelf -r bin/.opencode-wrapped | grep COPY
    000006510e40  R_X86_64_COPY  stderr@GLIBC_2.2.5 + 0
    000006510e20  R_X86_64_COPY  environ@GLIBC_2.2.5 + 0
    000006510e28  R_X86_64_COPY  stdout@GLIBC_2.2.5 + 0
    

    The binary's PT_LOAD segments are not in ascending p_vaddr order — the 85MB
    .bun payload segment is emitted first:

    $ readelf -lW bin/.opencode-wrapped | awk '/LOAD/{print $3, $6}'
    0x0000000006511000 0x515f000   <-- .bun payload, first
    0x00000000001ff000 0x001000
    0x0000000000200000 0x2806560
    0x0000000002b20c00 0x386f210
    0x0000000006390e10 0x180038    <-- RW/bss, ends at 0x6510e48
    

    The ELF spec requires PT_LOAD entries to be sorted by p_vaddr, and the
    kernel's ELF loader relies on that to size the .bss mapping. With the
    ordering wrong, the final page of .bss never gets mapped — and the three
    copy relocations above land in exactly that page. ld.so faults on the first
    one it writes.

    Why it's WSL2-specific

    Mainline kernels tolerate the bad ordering; the WSL2 kernel does not. That's
    consistent with the package building and caching fine on Hydra while failing
    on every WSL2 machine.

    It also explains a detail worth knowing for anyone trying to debug this under
    Nix: you cannot rebuild opencode locally on WSL2, because the build script's
    own smoke test crashes:

    building opencode-linux-x64
    Running smoke test: dist/opencode-linux-x64/bin/opencode --version
    Smoke test failed for opencode-linux-x64: ShellError: Failed with exit code 139
    

    That dist/ binary is pre-patchelf, straight out of bun build --compile, so
    the malformed layout is present the moment the executable is compiled — it is
    not introduced by any later Nix-side patching. Since the install-script binary
    reportedly works on WSL2, the released artifacts appear to have a correct
    segment order, which suggests this comes from how the binary is compiled in
    this build rather than from anything inherent to the released build. Running
    the readelf -lW command above against a release binary and a locally
    compiled one would confirm that directly.

    Fix / workaround

    Rewriting the interpreter to the value it already has is semantically a no-op,
    but it forces patchelf to regenerate the program header table, which emits the
    segments correctly sorted:

    patchelf --set-interpreter "$(patchelf --print-interpreter FILE)" FILE
    

    (Thanks @sonowz!)

    After that the .bun segment moves from first to last and the binary starts.
    Verified on 1.18.4 and reproduced identically on 1.18.11 (byte-identical
    segment addresses, so version bumps alone won't help).

    For nixpkgs users, this has to post-process the cached build rather than use
    overrideAttrs, since any override triggers the local rebuild that fails the
    smoke test above. The nixpkgs wrapper also hardcodes the original store path,
    so the fixed inner binary needs a fresh wrapper.

    A couple of questions for anyone who knows the build better than I do: is
    emitting sorted program headers something that can be controlled at compile
    time here, or is the post-hoc rewrite the practical route? And would a segment
    ordering check be worth adding to the release pipeline? The existing smoke test
    does catch this, but only on a kernel strict enough to fault, so it passes CI
    and surfaces later on WSL2.

    Happy to test any patch on a WSL2 box.

  10. Moritz-Dorn commented on Aug 4, 2026

    @Moritz-Dorn

    hi,

    Just had the same problem and also ran it down with Opus.

    Confirming this on 1.18.12 with the readelf comparison you asked for, plus a
    caveat about the patchelf workaround.

    NixOS 25.05 (glibc 2.40), WSL2 kernel 6.6.87.2-microsoft-standard-WSL2.

    Release vs. locally built: segment order

    Release tarball (opencode-linux-x64.tar.gz, v1.18.12), --version works:

    $ readelf -lW opencode | awk '/LOAD/{print $3, $6}'
    0x0000000000200000 0x2063270
    0x00000000024c8400 0x36e5770
    0x0000000005baeb70 0x53b5490 <-- .bun payload, last, ascending
    
    

    Locally built from the flake (same version, segfaults):

    0x0000000006511000 0x5171000 <-- .bun payload, first
    0x00000000001ff000 0x001000
    0x0000000000200000 0x2806560
    0x0000000002b20c00 0x386f210
    0x0000000006390e10 0x180038
    
    

    So the released artifacts do have correct ordering and the local build does
    not — this comes from the build, not from the format. Fault address is
    0x6510e40, byte-identical to your 1.18.4 and 1.18.11 despite a 178 MB
    payload here vs. your 85 MB. Version bumps and payload size don't move it.

    Also not glibc-dependent: forcing the binary through the older 2.40 loader
    (ld-linux-x86-64.so.2 <binary> --version) faults identically.

    Caveat: not every patchelf invocation is safe

    --set-interpreter fixes it, but patchelf in general does not. Running
    --set-rpath on a working release binary breaks it:

    $ ./opencode --version # 1.18.12, exit 0
    $ cp opencode oc-patched
    $ patchelf --set-rpath /tmp oc-patched
    $ ./oc-patched --version # SIGSEGV
    
    

    Different failure mode, not a re-ordering issue:

    local build release + --set-rpath
    fault addr 0x6510e40 0x495fd9c6
    error code 6 (write) 4 (read)
    FS register valid 0
    PT_LOAD order unsorted still ascending

    Segment order stays correct after --set-rpath (patchelf just prepends a
    segment at 0x1ff000 for the new header table), and the fault is a read at an
    address outside every mapping, before TLS setup. Looks like shifted file
    offsets invalidating Bun's recorded pointers into the appended blob — i.e. a
    second, independent way to break these binaries. Both reproduce with identical
    addresses across runs.

    Worth flagging since the workaround is itself a patchelf call: it has to be
    that specific no-op --set-interpreter and nothing else.

    Alternative for Nix users

    Skipping the local build entirely sidesteps both issues — fetch the release
    tarball, keep patchelf away from it, and let nix-ld provide the interpreter:

    pkgs.stdenvNoCC.mkDerivation rec {
      pname = "opencode";
      version = "1.18.12";
      src = pkgs.fetchurl {
        url = "https://github.com/anomalyco/opencode/releases/download/v${version}/opencode-linux-x64.tar.gz";
        hash = "sha256-ei47cGMGsE+/U1O2fZFrCAH82lZfnuAhvqKncgeWFFI=";
      };
      sourceRoot = ".";
      dontFixup = true;
      installPhase = "install -Dm755 opencode $out/bin/opencode";
    }

    with programs.nix-ld.enable = true;. No local build, no post-processing of a
    cached output, no wrapper rewrite. Running on WSL2 here.

  11. github-actions commented on Oct 5, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

  12. kd2flz commented on Oct 14, 2026

    @kd2flz

    Is this really not going to be fixed upstream?

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