Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Qwen Code 401 — A Field Guide

One valid key, three doors — two flash 401, one opens

MIT license zero keys printed battle-tested

TL;DR 401 invalid access token or token expired from an sk-sp- key that the console says is valid = wrong endpoint, not dead key. Find the one door your key type opens (§1), prove it with a real completion — never /models (§2) — and point every baseUrl at it (§4).

The error:

Internal error: 401 invalid access token or token expired

The trap: this message makes you think your API key is dead — but the provider console says the key is valid, regenerating it doesn't help, and reinstalling the extension doesn't help either. That's because for sk-sp- keys, this 401 usually means the key is being sent to the wrong endpoint, not that it expired. The wrong-door response is byte-identical to the expired-key response.

This guide is the result of debugging that exact loop end-to-end: the key taxonomy nobody explains, an endpoint matrix, a diagnosis method that can't be fooled, working config templates, and an audit script for comparing machines.

Jump to
§1 The root cause one prefix, three products
§2 The /models trap the sanity check that lies
§3 Diagnosis four steps, can't be fooled
§4 The fix working config + template
§5 Gotchas red herrings & caps
§6 Audit script compare machines, zero keys printed

1. 🗝️ The root cause: one prefix, three products

Alibaba Cloud's Qwen ecosystem has (at least) three different credential types that all get called "the API key":

Key type Looks like Works ONLY against
Standard Model Studio sk- + 32 hex (~35 chars) General endpoints: dashscope.aliyuncs.com (China) / dashscope-intl… / dashscope-us… /compatible-mode/v1
Coding Plan (individual, weekly quota) sk-sp-… (long, may contain dots) coding.dashscope.aliyuncs.com/v1 (China) / coding-intl.dashscope.aliyuncs.com/v1 (global)
Token Plan (teams, usage-billed) sk-sp-… (long, may contain dots) token-plan.<region>.maas.aliyuncs.com/compatible-mode/v1 (e.g. ap-southeast-1, cn-beijing)

Three things make this brutal to debug:

  1. Coding Plan and Token Plan keys share the sk-sp- prefix but are different products with different exclusive endpoints. You cannot tell them apart by looking at the key.
  2. Every wrong pairing returns the same 401 — "invalid access token or token expired" — whether the key is genuinely dead, from the wrong product, or from the wrong region.
  3. Keys are also region-scoped: a China-console key fails on international endpoints and vice versa, again with the same message.

The official error-code page confirms the plan-key rule ("dedicated API keys … must not be mixed with the general API Key/Base URL"): https://www.alibabacloud.com/help/en/model-studio/error-code#apikey-error

2. 🕳️ The /models trap — do not trust it

Some of the plan endpoints' /v1/models routes accept any Bearer token, including complete garbage. A 200 from /models does NOT mean your key is valid there.

Only /chat/completions validates the key. Always test with a real, tiny completion — and run a garbage-key control against the same route so you know whether that route checks auth at all:

# real test — a 401 here is meaningful; a 200 means the pairing works
curl -s https://<candidate-endpoint>/chat/completions \
  -H "Authorization: Bearer $YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"model":"<a-model>","max_tokens":8,"messages":[{"role":"user","content":"Say OK"}]}'

# control — if a garbage key gets a 200 on some route, that route proves nothing

💡 Bonus tell: a 404 model_not_found is good news — the endpoint authenticated your key and only rejected the model name. You've found the right door; now list what it serves.

3. 🩺 Diagnosis in four steps

  1. Shape-check the key (without printing it): length and prefix. ~35 chars sk- + hex → Standard. Long sk-sp- → one of the two plans.
  2. Probe each candidate endpoint with a real completion (§2). Wrong doors 401; the right door returns 200 — or 404 model_not_found, which still means the auth succeeded.
  3. List the models the right door serves (GET /v1/models on the door that validated) and use exactly those IDs. Note: unlisted models sometimes still work — the listing can lag the entitlement.
  4. Only if every door rejects it is the key actually dead — regenerate it in the console then. Remember regeneration invalidates the old key on every machine that has a copy.

4. 🔧 The fix — Qwen Code configuration that works

~/.qwen/settings.json (macOS/Linux; C:\Users\<you>\.qwen\ on Windows) — see settings.template.json for the full file:

  • env: store the key under a name that says what it is (e.g. TOKEN_PLAN_API_KEY) — calling a plan key DASHSCOPE_API_KEY is exactly how it ends up pointed at DashScope endpoints later.
  • Every modelProviders entry: baseUrl = your key's one valid endpoint, envKey = that env name, model ids taken from what the endpoint actually serves.
  • model.name / model.baseUrl: your default model at the same endpoint.
  • security.auth.selectedType: "openai" (the OpenAI-compatible API-key path).
  • Reasoning-capable models take "generationConfig": {"extra_body": {"enable_thinking": true}}.

VSCode (user settings.json):

"qwen-code.provider": "api-key"

⚠️ Warning about the provider picker: selecting "Coding Plan" in the extension's provider picker can rewrite ~/.qwen/settings.json and re-point your key at coding-plan endpoints — if your key is a Token Plan key, that reintroduces the 401 you just fixed. With a hand-written config, prefer leaving the picker alone.

5. ⚠️ Related gotchas collected along the way

  • The free-tier red herring. Qwen's OAuth free tier was discontinued 2026-04-15, producing a wave of identical 401 reports (#3203, #3335, #3425). If you were on the free OAuth tier, your fix is different: run /auth and switch to a paid plan or another provider. Don't let those threads convince you a plan key is dead — different disease, same symptom.
  • Token Plan output cap: max_tokens tops out at 131,072 on the token-plan endpoint; if you configure thinking budgets, keep them well under that.
  • Console "valid" ≠ endpoint match. The key-management page tells you the key exists and is active — it does not tell you which endpoint your tooling is sending it to.
  • Copying configs between machines copies the confusion too. If machine A's config was fixed by switching endpoints (not by changing the key), copying just the key to machine B fixes nothing — copy the whole config.

6. 🔍 Auditing and comparing machines

qwen-audit.sh emits a diffable report of the entire Qwen Code surface — settings, auth type, providers, extension/CLI versions, and where key material lives — without ever printing a key (length, 6-char prefix, and a 12-hex-char SHA-256 fingerprint only, which is enough to tell "same key" from "different key" across machines).

./qwen-audit.sh > this-machine.txt          # config report
./qwen-audit.sh --live > this-machine.txt   # + real auth probe of 3 endpoints
diff other-machine.txt this-machine.txt

Written by Nathan Maine — from a real debugging session across two machines. MIT licensed; if it saves you the afternoon it cost me, pass it along.

About

Field guide: Qwen Code's 401 'invalid access token or token expired' usually means wrong endpoint, not dead key. Key taxonomy, endpoint matrix, diagnosis method, working config template, machine-audit script.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages