Skip to content

OpenCode V2 workspace starts with an empty credential store, so every run fails with provider-auth-unavailable #1992

Closed

Description

@marcusrbrown

On v0.130.0 with the OpenCode V2 workspace (OPENCODE_VERSION 2.2.0 from opencode-v2-pin.json), every run fails about 9 seconds in with providerFailureReason: provider-auth-unavailable. The V2 server has no provider credential, so every model call goes out without a key and the provider answers 401.

Evidence (production, read-only)

  • The run status frames carry failureKind: session-error and providerFailureReason: provider-auth-unavailable. In the gateway log, provider retry scheduled is followed by session.execution.failed (provider auth unavailable) and then provider rejected the request — failing run. This happens on every repository.
  • The egress proxy shows the workspace reaching the provider. POST https://<provider>/v1/messages?beta=true returned 401 Unauthorized 12 times.
  • The legacy credential file exists. /home/opencode/.local/share/opencode/auth.json is mode 600, owned by uid 10001, with top-level keys anthropic and openai. The entrypoint logged auth: provisioned.
  • The V2 server (opencode serve --stdio, uid 10001) runs with XDG_DATA_HOME=/home/opencode/.local/share and a fresh OPENCODE_DB=/var/lib/workspace-agent/opencode-v2-db/spawn-*/opencode.db. That database's credential table is empty: SELECT integration_id, count(*) FROM credential GROUP BY 1 returns no rows. The workspace log has no credential-import line or error.
  • OPENCODE_CONFIG_CONTENT has no provider key and no model, but the workspace log reports model=set, provider-overlay=applied. I haven't found where the V2 server reads that overlay.

On v0.129.0 (V1, OpenCode 1.19.4) the same credential file and provider config worked, and runs reached the model.

Expected

A V2 spawn should end up with the provisioned credentials in its credential store. Either the legacy auth.json import runs against the fresh per-spawn database, or the workspace writes the credential into the V2 store directly. It should fail loudly at spawn when the store is empty, not at the first model call.

Related

V2 2.2.0 also fetches its model catalog from models.opencode.ai, which the egress allowlist blocks (403). It falls back to the bundled snapshot. That's a separate issue, and I'm handling it on the deploy side.

Activity

  1. fro-bot commented on Oct 30, 2026

    @fro-bot
    Owner

    Triage: confirmed credential-bootstrap regression

    Recommended priority: P1. The reported fleet-wide model failures are consistent with a locally reproduced V2 credential-provisioning defect.

    Root cause

    OpenCode 2.2.0 has a legacy auth.json importer, but fresh databases skip it:

    • In upstream DatabaseMigration.apply, an empty database receives the current schema and every migration is recorded as completed, without executing the individual migration bodies.
    • The import_legacy_credentials migration is therefore marked complete without reading auth.json.
    • Our workspace creates a fresh database for every spawn, while provisioning writes only the legacy file. No provider-credential gate runs before readiness. The supervisor's “credential holder” contains the server's Basic authentication password, not provider keys.

    This explains both the empty table and the absence of an import log. Restarting repeats the failure.

    Reproduction

    Using the checksum-verified stock 2.2.0 Linux binary, an isolated HOME/XDG tree, dummy Anthropic/OpenAI keys, and the production provisioning helper:

    1. Provisioned auth.json and a provider/model overlay before starting the server.
    2. Started serve --stdio against a fresh OPENCODE_DB.
    3. Observed /api/agent ready, /api/credential empty, and the legacy-import migration recorded complete.
    4. Verified POST /api/credential successfully stored and activated a dummy key.
    5. Repeated with another fresh database: credentials were empty again.

    The overlay is being read: /api/config exposed the provider URL and model from $XDG_CONFIG_HOME/opencode/opencode.json, although neither appeared in OPENCODE_CONFIG_CONTENT. That omission alone is not a configuration failure.

    This reproduces the credential loss/readiness defect; I did not replay a production provider request or independently reproduce its 401. Focused existing tests passed: 91 passed, with 2 real-binary integration tests skipped. The standalone reproduction above exercised the downloaded binary. Existing workspace integration coverage embeds an apiKey directly in provider options, bypassing this legacy-file path.

    Next steps

    1. Seed credentials on every V2 spawn, preferably through the authenticated POST /api/credential API before publishing readiness. Convert legacy API entries from {type: "api", key} to V2 {integrationID, value: {type: "key", key}}; keep secrets out of argv and logs.
    2. Verify the provisioned credentials are active before admitting model runs; emit a clear provisioning failure instead of deferring to the first request. Preserve credential-free clone-only boot.
    3. Add a regression test using legacy-file-only credentials, two fresh spawns, and a local provider that asserts the received authentication header.
    4. Report the fresh-bootstrap importer omission upstream. Keep the model-catalog egress issue separate.

    Run Summary
    Field Value
    Event issues
    Repository fro-bot/agent
    Run ID 41076255983
    Cache hit
    Session ses_e72ae4303ffeWdb2jw82CfhfVz
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions