Skip to content

Provider API: working CLI key starts returning 401 authentication_error mid-use (2026-10-29), re-login fixes it — no local change involved #1084

Open

Description

@hayashishungenn

Summary

A long-lived CLI API key that was working normally started returning 401 authentication_error on every Provider API request on 2026-10-29, with no local change on my side. Re-signing in through the Studio CLI auth flow minted a new key that works immediately. Filing in case the revocation was unintentional (it overlaps the 2026-10-28 → 10-29 instability window) or affects other users.

Environment

  • Plan: GOAT
  • Client: command-code CLI credentials (~/.commandcode/auth.json), consumed through a local gateway that passes the key as Authorization: Bearer <key>
  • Key: cli-2026-10-16T07-27-19, user_-prefixed, 92 chars (created 2026-10-16, format per GOAT plan: Provider API returns 401 authentication_error on every request #1040)
  • Model in use: deepseek/deepseek-v4.1-flash
  • Not a quota problem: at failure time Credits showed ~$30 of $70 remaining, weekly window ~36.5 used with reset on 2026-10-30

Timeline (CST, UTC+8)

  • 2026-10-28 22:55 — last successful request with the old key (HTTP 200; ~420 successful requests through this key during 10-28)
  • 2026-10-29 00:03 — one request retried 8×, all 502 with "The socket connection was closed unexpectedly", then gave up
  • 2026-10-29 08:59 — first try 502, second try 401: Command Code Plan: Invalid 'Authorization' header or token.
  • 2026-10-29 09:00 onward — every request 401

What rules out a local cause

Trace from the failing key

HTTP/1.1 401 Unauthorized
Date: Thu, 29 Oct 2026 01:42:14 GMT
x-trace-id: 13dccdb25d9d0223b447f5ccce52106e
CF-RAY: a51e7b84ad69c238-NRT
{"error":{"message":"Invalid 'Authorization' header or token.","type":"authentication_error","code":"UNAUTHORIZED"}}

Resolution (workaround)

Re-running the Studio CLI sign-in (https://commandcode.ai/studio/auth/cli?...) minted a fresh key (cli-2026-10-29T02-02-42) and requests immediately return HTTP 200 again. Same account, same plan, nothing else changed.

Questions

  1. Was the old key revoked server-side on purpose (e.g. rotation/cleanup), or could it have been collateral from the instability around 2026-10-28/29 (502s at 00:03 CST, related to [Bug] api.commandcode.ai: 503 Cloudflare Error 1102 (worker_exceeded_resources) on every request since 2026-10-23 05:54 CST #1060's recurring Cloudflare worker incidents)?
  2. If intentional, is there a way to notice this in advance (the Billing API reports the account as healthy, cf. Billing API reports a healthy account while every request 400s with insufficient credits #1081), and should the CLI detect "key no longer valid" distinctly from "sign-in lapsed"?

Happy to provide the userId of the affected key if needed. Related: #1040 (same error string, user-side cause there), #1060 (service instability in the same window).

Activity

  1. FlyingDriver commented on Oct 29, 2026

    @FlyingDriver

    Confirming this is not isolated — same failure window, same account-side symptoms, plus one detail that may answer the "was this intentional?" question in the original report.

    Timeline (CST / UTC+8)

    • 2026-10-29 01:04:42 CST (2026-10-28 17:04:42 UTC) — last successful request, HTTP 200
    • 2026-10-29 09:12:58 CST (2026-10-29 01:12:58 UTC) — first 401 authentication_error
    • 2026-10-29 09:12 CST → 11:08 CST — 406 consecutive failures, no recovery
    • 2026-10-29 11:08 CST — replaced the key in our gateway; immediate recovery

    This overlaps the reporter's window (last success 22:55 CST, first 401 at 08:59 CST) within ~13 minutes at the start.

    The detail worth adding: two keys, two different error strings

    We held two long-lived keys on the same GOAT account. Both stopped working in the same window, but the upstream message differs — and the difference is informative:

    Key (masked) Length Upstream message
    user_… (93 chars, previously disabled) 93 Your API key has expired. Log in again to get a new key: run cmd login, or create a new key in Command Code Studio.
    user_… (92 chars, the one in active use) 92 Invalid 'Authorization' header or token.

    The 93-char key is told it has expired — an explicit expiry verdict, not a generic auth rejection. That suggests at least one key was retired under a deliberate expiry/rotation path on the server side, rather than being collateral from the Cloudflare 1102 instability in #1060. It would be worth confirming whether both keys hit the same code path.

    Ruled out on our side

    Not a quota problem. Billing state at failure time and now (/alpha/billing/credits, /alpha/billing/subscriptions, read with the replacement key):

    planId:            individual-goat
    status:            active
    currentPeriodEnd:  2026-11-07T07:24:07Z
    monthlyCredits:    27.96    (of the $80 boosted deepseek-v4.1-flash allowance)
    5-hour window:     0.14 / 14 used
    weekly window:     17.96 / 35 used
    

    No window exceeded, no balance exhaustion. Consistent with a 401 at the auth stage — the request never reached metering, so nothing was charged.

    Not a local change. No credential or config file was modified in our gateway between the last success and the first failure. The only change after the failures began was replacing the key, which fixed it.

    Not a request-shape problem. Results are identical across /provider/v1/chat/completions and /provider/v1/responses, and across models (deepseek/deepseek-v4.1-flash, gpt-5.6-luna, zai-org/GLM-5.3, moonshotai/Kimi-K3).

    Traces

    Old keys (failures), captured 2026-10-29 03:26 UTC:

    # 93-char key
    HTTP/2 401
    date: Thu, 29 Oct 2026 03:26:10 GMT
    x-trace-id: a54640bd1cf1edc7e76745bd8597e563
    cf-ray: a51f13c4adb71422-SJC
    {"error":{"message":"Invalid 'Authorization' header or token.","type":"authentication_error","code":"UNAUTHORIZED"}}
    
    # 92-char key
    HTTP/2 401
    date: Thu, 29 Oct 2026 03:26:11 GMT
    x-trace-id: 9af4203adc800d3a7f6763123ea47f4e
    cf-ray: a51f13c7cbd9ae99-SJC
    {"error":{"message":"Invalid 'Authorization' header or token.","type":"authentication_error","code":"UNAUTHORIZED"}}
    

    Control — the replacement key on the same request, ~19s later:

    HTTP/2 200
    date: Thu, 29 Oct 2026 03:26:30 GMT
    x-trace-id: bdc02639cc4942a78d41042c2756b4df
    cf-ray: a51f14393b5c2c47-SJC
    {"id":"1bacfe12cb03756d31ec841af307416b", ... ,"model":"deepseek/deepseek-v4.1-flash", ...}
    

    Same account, same plan, same endpoint, same body, same egress host — only the key differs. So the credential itself is the rejected artifact, not the request.

    Setup

    A self-hosted gateway forwards the key as Authorization: Bearer <key> — the same shape as the original report's local gateway. /provider/v1/models returns 200 without auth validation, so it is not usable as a health signal here; a real inference call is the only reliable check.

    Asks

    1. Was the 92/93-char key expiry intentional? The has expired wording on one key suggests a rotation/expiry path was deliberately triggered. If so, please publish the policy — keys silently expiring with no advance signal is the part that costs us real time.
    2. Please record this on the status page. https://status.commandcode.ai currently reports 100.00% uptime with no incident for the 2026-10-28 → 10-29 window. Together with [Bug] api.commandcode.ai: 503 Cloudflare Error 1102 (worker_exceeded_resources) on every request since 2026-10-23 05:54 CST #1060 (1102s), Billing API reports a healthy account while every request 400s with insufficient credits #1081, Fresh install of 1.88.1 fails on startup: '@opentelemetry/semantic-conventions' has no default export #1082/CLI fails to start: "does not provide an export named 'default'" from @opentelemetry/semantic-conventions@1.44.0 (v1.87.0 and v1.88.1, Node 22) #1083 and this report, that window was clearly degraded but appears nowhere in the public incident history.
    3. A proactive validity signal would prevent this class of outage. The Billing API reports the account as healthy while every request 401s (also noted in Billing API reports a healthy account while every request 400s with insufficient credits #1081), and command-code status reports "Authenticated" from the presence of a credential file rather than from a live check. Either a keyValid/canRequest-style field or a lightweight authenticated probe endpoint would let gateways fail over before burning requests.
    4. Related: GOAT plan: Provider API returns 401 authentication_error on every request #1040 (same error string, different root cause), [Bug] api.commandcode.ai: 503 Cloudflare Error 1102 (worker_exceeded_resources) on every request since 2026-10-23 05:54 CST #1060 (instability the same window), Billing API reports a healthy account while every request 400s with insufficient credits #1081 (billing reports healthy while requests fail).

    Happy to provide account id and the full keys privately if that helps you look them up by server-side key record.

  2. cenktekin commented on Oct 29, 2026

    @cenktekin

    Third independent report — same window, plus two details that may help pin this down.

    Environment: Windows 11, CLI 1.88.2, headless runs (cmd -p) driven by a local scheduler.

    Local timeline (UTC; the machine is UTC+3):

    • 2026-10-28 16:00Z — last successful scheduled headless run.
    • 2026-10-29 05:23:59Z — npm auto-update to 1.88.2 landed.
    • 2026-10-29 05:27:53Z — first failure. Two scheduled runs died with Error: Authentication failed. Please run "cmdc login" first. (exit code 3). ~/.commandcode/auth.json was still present and still contained the key — no credential file was modified between the last success and the first 401. So the update is not the trigger (neither reporter above had one); on this machine it just made the failure visible 4 minutes earlier.
    • 2026-10-29 05:39Z — cmdc login. The Studio flow minted a new CLI key, auto-named cli-2026-10-29T05-41-00.
    • 2026-10-29 05:40:57Z — local auth.json rewritten by the manual-key branch of the login flow; cmdc whoami OK, every request 200 since.
    • Trace from the failing CLI session: 29dce525a47473ca06842518a6066788.

    1. Revoked keys are hidden from the dashboard, which is what makes this unanswerable from the client side. Before re-login the Studio key list showed no keys at all — not a revoked/expired entry with a reason. From the UI it is impossible to distinguish "revoked on purpose 4 minutes ago" from "expired" from "never created". Listing revoked keys with a reason and a timestamp (even greyed out) would answer the core question of this issue without a support ticket.

    2. On 1.88.2, cmdc status is a live check, not a file-presence check (relevant to ask 3 above). I verified this in an isolated HOME/USERPROFILE so the real credential was untouched:

    • current key with one character mutated (format still valid, key invalid) → cmdc status prints Not authenticated and exits 1; cmdc whoami behaves the same (Not authenticated. Please login);
    • unmutated key → Authentication verified, exit 0.

    So an exit-code-based health probe does work on this version — it is what I gate scheduled runs on now. What would still help: a distinct exit code / message for "key revoked or expired" vs. "never signed in". A supervisor cannot tell them apart today, and that difference is exactly what decides between "re-authenticate" and "page a human".

    3. A ~13-day age pattern? The reporter's key was cli-2026-10-16T07-27-19 — created 10-16, dead 10-29, ≈13 days. Our previous credential died in the same window, but I cannot date it exactly because auth.json was overwritten by the re-login. One more data point: the credential we held before was visibly longer and shaped differently from the 93-char user_… key that login mints now (observed in the dashboard; no local copy survived). If the key scheme changed and/or there is a TTL, it should be documented — and ideally the CLI should warn a few days before expiry, because a silent expiry takes down unattended jobs with no signal whatsoever.

    Happy to provide the userId and the trace above privately.

  3. a404670637-ch commented on Oct 29, 2026

    @a404670637-ch

    Same failure mode here, on a paid GOAT plan and with quota nowhere near exhausted (Studio shows 5-hour window 0%, weekly 13%, monthly 75%, 2.4B tokens lifetime).

    Two keys were retired server-side within 12 hours, and both distinct upstream messages mentioned above showed up on this single account:

    • Key A (92 chars, user_j616i1s…): last successful request 2026-10-28 17:45:46 CST (UTC+8). First 401 at 2026-10-29 04:01:32 CST:
      {"error":{"message":"Invalid 'Authorization' header or token.","type":"authentication_error","code":"UNAUTHORIZED"}}
      It then disappeared from Studio → API keys.
    • Key B (92 chars, user_gxYcf5E…, created ~2026-10-29 04:00 CST): worked continuously 04:13–06:57:57 CST (446 successful requests). First 401 at 06:59:31 CST:
      Your API key has expired. Log in again to get a new key: run \cmd login`, or create a new key in Command Code Studio.`
      — an explicit expiry verdict, roughly 2h50m after creation. Studio now lists it with an "expired" badge.
    • Key C (93 chars, created 13:46 CST): still working at the time of writing.

    Reproduced outside the local gateway with plain curl against POST https://api.commandcode.ai/provider/v1/chat/completions (key A): HTTP 401 with the identical body, x-trace-id: 0282e57f4b1b75de8bafd830dca0c882, cf-ray: …-SIN.

    Client chain: Cherry Studio 2.1.8 local OpenAI-compatible gateway → https://api.commandcode.ai/provider/v1, streaming, deepseek/deepseek-v4.1-flash, Windows 10 x64, single machine. Nothing changed locally between the last success and the first failure, and the stored key strings are intact (92 chars, same format as the working key in #1040).

    So this is not quota, not a model/plan gate, and not a request-shape problem: keys are being retired server-side, one of them with an explicit "expired" verdict.

    Questions:

    1. Is there now an API-key TTL / rotation policy? The docs (Studio, Provider API, Security, Terms) and the Studio UI don't mention one. If it exists, what is the TTL, and why did a key created around 04:00 CST expire at 06:59?
    2. Was the 2026-10-28 → 10-29 retirement wave an incident response, a key-format migration (92 → 93 chars), or a deliberate revocation?
    3. Could the API/CLI surface a distinct "key expired — re-authenticate" state (as the newer message does) instead of a mid-use generic 401, and is there any advance notice by email or in-app?

    Happy to share the account/key identifiers privately if useful.

  4. cenktekin commented on Oct 29, 2026

    @cenktekin

    Addendum to my report above — one state that is missing from this thread so far: the key list was empty, not "expired".

    Details that don't match the other two cases:

    • Before re-login, Studio → API keys listed zero keys for the account. No expired badge, no greyed-out entry, no "removed" row — an empty list. The other report in this thread shows Studio can render a retired key with an explicit expired badge, so "expired" and "gone" appear to be two different end states, not the same one.
    • The CLI, meanwhile, collapses both into one message: Your API key may be invalid or expired. Run "cmdc login" to sign in again. (trace 29dce525a47473ca06842518a6066788). So from the client the user cannot tell "expired — re-authenticate" from "removed — something else happened".
    • The replacement credential minted at 2026-10-29T05:40:57Z is user_-prefixed, 93 chars, and has been healthy since (same account, same plan, no other change). That is consistent with the 92 → 93 char split noted above: the new-format key works.

    Ask: was the previous key deleted, or expired-and-then-hidden? A key audit trail in Studio — created / expired / revoked / deleted, each with a timestamp and an actor (user vs system) — would answer this class of question in one screen, and would also make the next incident self-diagnosable without a support thread. Email or in-app notice on revocation would cover the "no advance signal" part.

  5. dondiegorivera commented on Oct 29, 2026

    @dondiegorivera

    I have the same failure. First, my key was deleted. I recreated it yesterday, then by the morning it expired.

  6. naymurdev commented on Oct 29, 2026

    @naymurdev

    @dondiegorivera sorry for that inconvenience, please create new API

  7. vipulgupta2048 commented on Oct 29, 2026

    @vipulgupta2048
    Contributor

    Thanks for the reports @cenktekin @dondiegorivera @hayashishungenn @a404670637-ch @FlyingDriver
    All API keys were revoked for users. As a final precaution, we once again purged all API keys that you might created in the interim.

    Services are back to normal now, please recreate your API keys, it should work now.
    Context: https://discord.com/channels/1255220079029653626/1255287193656623266/1565143125503254560

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

      ⌂ Proxy