Skip to content

auth: expired Console credential gives a non-actionable error, and 400/429 during re-auth are never logged #56782

Open

Description

@demond86

Summary

Three client-side problems in the Console auth flow, observed on 2026-10-17:

  1. An expired Console credential produces an error that doesn't match the credential type
    and doesn't name the command that actually fixes it.
  2. POST /api/integration/opencode/connect/oauth failing with 400 leaves no trace of
    why — the log has only the status code.
  3. A 429 from the device-code flow never reaches opencode.log at all and no retry-after
    is surfaced, so the client retries blindly.

Together this made it impossible to tell "my credential is dead" from "the service is down".

This report is about diagnostics and error text only, not about the outage itself.

Environment

  • opencode version: 2.0.32 (reproduced identically on 2.0.29 — CLI was upgraded mid-incident)
  • OS: Windows_NT 10.0.19045 (win32 x64)
  • Terminal: VS Code terminal (TERM_PROGRAM=vscode, COLORTERM=truecolor), shell C:\Windows\system32\cmd.exe
  • Install/channel: release
  • Active plugins: none ("plugins": [] in ~/.config/opencode/opencode.jsonc);
    two plugin files exist in ~/.config/opencode/plugins/ (opencode-ignore.ts, read-image.ts)
    but are not referenced from the config
  • MCP servers: none
  • Storage health: writable; opencode service status returns a healthy endpoint

Reproduction

All times UTC+3, 2026-10-17.

  1. Have a Console credential stored (created earlier via opencode auth login).
  2. The server starts rejecting it:
    • 20:11 — first 401 GET https://opencode.ai/console/api/v2/config, logged as WARN
      failed to load OpenCode provider config (69 such entries that day)
    • 20:11–20:48 — 6x ERROR Failed to drain Session across 3 sessions, cause:
      AI.Error.Authentication("This API key has expired. Visit https://opencode.com/settings/auth to create a new API key. Signing in again will not renew this key.")
  3. Try to re-authenticate:
    • 20:20 — first POST /api/integration/opencode/connect/oauth -> 400. Six attempts
      total (2.0.29 and 2.0.32), all identical. The log records only http.status=400:
      no response body, no cause, and the CLI shows no reason either.
    • 20:29–20:49 — opencode auth login retried: 429 POST https://opencode.ai/console/auth/device/code. This 429 never appears in
      opencode.log, and no retry-after is shown, so retries were blind.
  4. Recovery: at 20:59:41 credential created integrationID=opencode type=oauth after a
    normal opencode auth login; every request worked again from that moment on.

Expected Behavior

  • A credential error names the recovery path that actually works for that credential type.
  • Failed auth HTTP responses log enough to diagnose them (body/cause, not just status).
  • Rate-limited responses are visible locally and produce a readable retry-after and backoff.

Actual Behavior

  • The credential was type=oauth, created by opencode auth login — the user never
    created an API key, yet the message instructs creating one in Console settings and
    does not mention opencode auth login, which is what actually fixed it.
  • A credential stored by the connect flow at 20:32 was accepted and then failed ~13 s
    later with the same "expired" error — the connect path accepted a dead key without
    validating it.
  • Six connect/oauth 400s over ~30 minutes are indistinguishable in the log: three
    different underlying failures all look like http.status=400.
  • Zero log entries for the 429; the CLI output for all ~6 attempts was identical
    (Starting device login... with no reason, no wait time).

Frequency

Consistent: every connect/oauth attempt during the window failed the same way, and
every 429 attempt produced identical output.

Asked

  • Surface the response body/cause of connect/oauth 400s, in the log and in CLI output.
  • Log rate-limit (429) responses from the device-code flow and show a readable
    retry-after; back off instead of retrying immediately.
  • Validate a credential at connect time, so a dead key fails there rather than on the
    first model request.
  • For Console OAuth credentials, make the expired-credential message name
    opencode auth login as the recovery command.

Activity

  1. opencode-agent commented on Oct 18, 2026

    @opencode-agent
    Contributor

    Thanks for the detailed timeline. Separating your own setup from what the CLI reports makes this easy to follow.

    To sum up the request: when Console sign-in breaks, OpenCode should tell you what went wrong and how to fix it. That means:

    • an expired-credential message that names opencode auth login for Console sign-in credentials
    • the response body or cause of connect/oauth 400s, in the log and in the CLI
    • device-code 429s logged locally, with a readable wait time and backoff
    • a credential checked when it is connected, so a dead one fails there

    I've filed this as a feature request, and maintainers will consider it.

    Some parts overlap with open issues:

  2. reynold-hu commented on Oct 18, 2026

    @reynold-hu
    Contributor

    I'll take the diagnostics half of this: (1) device-code and connect/oauth HTTP failures will log and surface the response body plus retry-after (including 429), and (2) the Console OAuth expired-credential message will name opencode auth login as the recovery command. Validating a credential at connect time is a separate behavior change; I'll leave that as a follow-up unless a maintainer wants it in the same PR.

  3. reynold-hu commented on Oct 18, 2026

    @reynold-hu
    Contributor

    Opened #56791 for the diagnostics half: failed Console responses now keep their body and retry-after in the log and in the error the CLI prints, and the signed-out message names opencode auth login. The new 429 test fails on the parent commit with only non 2xx status code (429 ...) and passes with the change. Credential validation at connect time is left as a follow-up.

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions