Skip to content

Updater offers in-app updates for Nix store installs; taking it breaks the running session #54022

Open

Description

@fabiob

Description

opencode installed via this repo's Nix flake lives in the read-only Nix store. The TUI still offers the in-app update — accepting it starts the self-updater, which cannot replace the binary, and the session stops responding until the processes are killed. After that, opencode starts again.

The updater already special-cases curl and Homebrew installs (Cellar path check). A Nix store install (/nix/store/... executable, no npm manifest) falls through to method() → undefined and is still offered updates. Skipping — or reporting itself unavailable — for those, like the Homebrew case, would fix it.

OpenCode version

2.0.26 (built from this repo's flake, nix/opencode.nix)

Steps to reproduce

  1. NixOS, install opencode via the repo flake
  2. Open the TUI
  3. Accept the update prompt when it appears

Activity

  1. opencode-agent commented on Oct 8, 2026

    @opencode-agent
    Contributor

    Thanks for the report. I could reproduce the main part of this with a simulated Nix-store install: a released binary in a read-only /nix/store-style directory with no npm manifest, so the updater can't detect how it was installed. I used 2.0.25 so that a newer release would be offered. There's no Nix in my sandbox, so I didn't build the actual flake.

    • /update (and the home-screen hint) still offers the update, with an Update button.
    • Accepting it fails with Installation method not found, and the update stays on offer afterwards.

    In my run the session did not hang: after the error I could close the dialog and keep typing. The hang you saw may depend on something only the real flake build has, such as the wrapProgram wrapper or the real store path. If you can share the log lines around the update attempt (the update / updater entries in the opencode log), that would help pin it down.

    I couldn't run this check from source, because source checkouts skip update checks. But the updater and the Nix packaging are unchanged on the latest v2 (a2e3dd2), so the same behaviour is expected there. The recording and script below show the steps. Your PR #54021 sets OPENCODE_DISABLE_AUTOUPDATE=1 in the flake wrapper, which avoids this for flake installs. #52122 is the same problem in the Nix desktop build.

    recording.mp4

    Screenshot

    Screenshot

    Reproduction script (drive.ts)
    // Repro for #54022: in-app update offered for a Nix-store-style install.
    // Setup: put an opencode binary in a read-only /nix/store-like path with no
    // package.json next to it (so Updater.method() returns undefined), first on PATH:
    //   S=/tmp/opencode/nix/store/abc123-opencode-2.0.25/bin; mkdir -p $S
    //   (copy the @opencode/[email protected] binary to $S/opencode); chmod -R a-w $S
    //   export PATH=$S:$PATH
    // 2.0.25 is used so that a newer release (2.0.26+) is offered.
    import { Effect } from "effect"
    import { OpenCodeDriver } from "opencode-drive"
    
    export default OpenCodeDriver.use(
      {
        ...(process.env.OC_DEV ? { opencode: { dev: process.env.OC_DEV } } : {}),
        tui: { recording: true, keypressOverlay: true },
      },
      ({ ui }) =>
        Effect.gen(function* () {
          yield* Effect.sleep("6 seconds")
          yield* ui.screenshot("01-home")
          yield* ui.type("/update")
          yield* Effect.sleep("1 second")
          yield* ui.screenshot("02-command")
          yield* ui.enter()
          yield* Effect.sleep("8 seconds")
          yield* ui.screenshot("03-dialog")
          yield* ui.enter()
          yield* Effect.sleep("15 seconds")
          yield* ui.screenshot("04-after-accept")
          yield* ui.press("escape")
          yield* Effect.sleep("2 seconds")
          yield* ui.type("hello still responsive?")
          yield* Effect.sleep("2 seconds")
          yield* ui.screenshot("05-responsive")
        }),
    )

    Run it with opencode-drive: opencode-drive run ./drive.ts. It drives opencode from your PATH; set OC_DEV to the path of an OpenCode checkout to run that from source instead.

  2. fabiob commented on Oct 22, 2026

    @fabiob
    ContributorAuthor

    Status update, since the fix landed in two pieces:

    One gap that remains untracked: the desktop client's own updater (electron-updater in packages/gui-extensions/src/updater/) reads neither the variable nor any installation-method detection, so a Nix store install of the desktop app can still be offered an update it cannot apply (see carterworks' note above). A fix there would follow the same shape — detect a store install and report the updater disabled (the state already exists). Happy to file a separate issue for it if useful.

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions