Skip to content

service (v2): serve --service daemon keeps using old OPENCODE_API_KEY after the key is rotated (401 with no hint) #42690

Open

Description

@bharatagarwal

Summary

After rotating my OPENCODE_API_KEY, opencode2 kept failing with Provider request failed with HTTP 401: Invalid API key — from fresh shells, even though the new key was valid. The cause: a background opencode2 serve --service process started days earlier (before the rotation) was still holding the old key in its environment, and all CLI requests routed through that stale server. Killing the daemon fixed it immediately.

Environment

  • opencode version: 0.0.0-next-17403 (next channel, v2 beta)
  • OS: macOS (Darwin, arm64)
  • Install: local binary in ~/.opencode/bin
  • Credential: OPENCODE_API_KEY set via env var in shell profile

Reproduction

  1. Start opencode2 serve --service (or just start a session) with a valid OPENCODE_API_KEY.
  2. Rotate the key: change OPENCODE_API_KEY in the environment for new shells.
  3. Open a fresh shell and run opencode2 run "hi".

Actual result

Error: Provider request failed with HTTP 401: Invalid API key.

The error gives no indication that the running server process was started with a different (now-revoked) key. I confirmed the new key was valid by calling the provider endpoint directly (curl with the new key returns 200). ps showed the daemon had been running since before the rotation.

Expected result

Some signal that the running serve --service daemon may hold an outdated credential — e.g. the 401 error mentioning the running server process — would have made this a 30-second fix instead of a debugging session. Restarting the daemon (kill + rerun) resolves it.

Possibly related to the daemon-lifecycle issues #37239 and #42270.

Activity

  1. nexxeln commented on Aug 18, 2026

    @nexxeln
    Contributor

    The background service may be using outdated environment credentials. Restart it with opencode2 service restart.

  2. aleks-mariusz commented on Oct 12, 2026

    @aleks-mariusz

    Just hit this as well, and the failure mode is nasty to debug. I launch opencode through a liteLLM CLI wrapper (lite opencode) that injects a fresh short-lived (24h) API token into the child env on every run. Since the shared background service captures its env once at spawn, once that token expired every subsequent launch silently routed through the stale daemon and failed with an "Expired Key" 401 — even though the wrapper was handing over a perfectly valid new token. Re-login didn't help; only killing the daemon did. So this isn't just a manual key-rotation edge case: any short-lived-credential workflow triggers it deterministically, with no hint in the error that a stale server env is the cause.

    Update — a working solution exists: PR #52107 added opencode service set disabled true (merged 2026-09-29, shipping in current releases), which disables the background service entirely and makes the CLI default to private standalone servers. Running that one command fixed my case permanently: every launch now spawns a private server with the current env, so there's no daemon to hold onto a stale token. For anyone else landing here on rotating/short-lived credentials, that toggle is the workaround that ships today. The complementary fix would still be what this issue asks for (env mismatch detection, respawn-or-inherit), since users who want the shared service shouldn't have to choose it vs. fresh credentials.

  3. opencodejr commented on Oct 28, 2026

    @opencodejr

    Thanks for the clear write-up and for tracking down the cause.

    This comes from how the shared background service is designed. opencode2 reuses the running serve --service process as long as its version matches. That process keeps the environment it was started with, so a rotated OPENCODE_API_KEY in a new shell doesn't reach it until it's restarted (opencode2 service restart). Since the service is doing what it was built to do, I've filed this as a feature request: show a clear hint when a provider returns 401 and the request went through a long-running service that may hold an outdated credential. For example, the CLI could warn when its own key differs from the service's, or the error could mention the service and suggest restarting it. Maintainers will consider it.

    Related issues:

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions