I asked a simple question: why is it falling back?
The home agent was supposed to answer on the Qwen default I had already configured. It didn't. A fallback answered instead. My first guess was the usual one — maybe the model id drifted, maybe the default never stuck, maybe I typed the wrong name.
Then I looked at the HTTP status.
Alibaba was returning 401. Invalid API-key. The default was still Qwen. The provider was rejecting the credential. That is a different failure from "you picked the wrong model."
The status code is the first question
I have already lived through quota and rate-limit nights. Those are 429-shaped problems. This was not that.
Alibaba Cloud Model Studio documents HTTP 401 InvalidApiKey / invalid_api_key with messages like "Invalid API-key provided" and "Incorrect API key provided." It treats 401 as an authentication failure, not as "this model does not exist." The documented mix-ups are boring and easy to make:
- a wrong or mistyped key
- extra spaces
- another provider's key sitting in the Qwen slot
- a Coding Plan or Token Plan Team Edition exclusive
sk-sp-key used with the general API key or base URL - a key from one region used against another region's base URL
That last one looks identical to a typo. A Model Studio API key is bound to the region where it was created. Call a different region's endpoint and you can get the same 401 / "Incorrect API key provided" as a mistype. The error looks like "bad key." The cause can be "right key, wrong door."
Quota exhaustion is documented separately: hour/week/month allocated quota exceeded, plus 429 usage allocated quota. Retrying a 401 as if it were a 429 will not fix a rejected credential. OpenClaw is explicit about the same split. It rotates to an alternate env key only for rate-limit, 429, or quota phrasing. Other errors, including a rejected credential, are not retried with alternate keys. A 401 stays a 401. It does not quietly try the next secret and pretend the default is healthy.
Keys and URLs come in matching pairs
Pay-as-you-go Model Studio keys are not the Token Plan or Coding Plan path. Those plans use a dedicated key starting with sk-sp-. Each region has its own endpoint, API keys, and model list. They cannot be used across regions.
Token Plan keys start with sk-sp- and are not interchangeable with standard Model Studio sk- keys. Token Plan, Coding Plan, and pay-as-you-go keys and base URLs are isolated. They have to be used in matching pairs. Mix them and you can land on pay-as-you-go, or you can get a 401 or 403 authentication error.
Coding Plan's FAQ documents 401 "invalid access token or token expired" when you send a general-purpose sk-xxx key instead of the plan-specific one. Expired and malformed keys live in that same bucket. Wrong base URL for Coding Plan is documented as 403 invalid api-key. The general error-code page groups plan and base-URL mixing under 401. Flattening those into one status code would make the docs tidier than they are.
The China Token Plan OpenAI-compatible base URL is https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1. OpenClaw treats Token Plan as a separate provider, qwen-token-plan. The preferred env var for Qwen is QWEN_API_KEY. The Token Plan env var is QWEN_TOKEN_PLAN_API_KEY. The Global/International Token Plan endpoint is token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1.
Those URLs are the documented pairing, not a confession of my live route. Use the pair that matches the key.
OpenClaw's Qwen page is also blunt about where Token Plan belongs: interactive sessions. Alibaba can suspend non-interactive Token Plan use. I am not going to recommend it for cron.
Configured default is not this turn's model
OpenClaw failover is two stages:
- auth-profile rotation within the same provider
- model fallback to
agents.defaults.model.fallbacks
Cooldowns apply to failing profiles, including auth failures, with exponential backoff. That is how a configured default can still be Qwen while this turn answers on a fallback. The auth profile is in cooldown. Later turns skip the unavailable profile and keep responding.
A failing auth profile can show up under unavailable or unusable profiles. That does not mean every model on that provider is dead. Rate-limit cooldowns can be model-scoped. Sibling models on the same provider may still be eligible. I asked "why is it falling back?" and the honest answer was "this profile was rejected," not "Qwen as a category is gone."
Secrets and runtime auth-routing state live in per-agent SQLite auth profiles. Config auth.profiles and auth.order are metadata plus routing. They are not the live secret. Fallback for a configured default is turn-local: the model that answered can differ from the selected primary without becoming the next turn's selection.
That last sentence is the one that made the night less confusing. Seeing a fallback answer does not rewrite the default. It means this turn could not use the primary.
Three places a key can live
Credential checks can come from:
- auth profiles
- env credentials
models.json
They are separate sources. Editing one does not automatically update the others. I am not going to claim SQLite always beats env, or that touching an env var can never affect routing. Precedence is not a product rule I fetched. The useful rule is narrower: if you change one store and the gateway still sends a rejected credential, look at the other stores before you invent a model-id bug.
The inspection command that actually answers this is openclaw models status. It shows the resolved default and fallbacks plus an auth overview. Active profile cooldowns appear under "Unavailable auth profiles." JSON exposes auth.unusableProfiles.
If the key itself needs replacing, models auth paste-api-key --provider <id> can save a key to a running Gateway and refresh the catalog without a restart. Replacing a saved API key clears that profile's previous cooldown. An explicit --profile-id is not supported by the Gateway API while the Gateway is running. Omit it, or stop the Gateway and run offline. I am not going to paste a live-key how-to. The documented live-Gateway path is provider-scoped paste.
The small rule I am keeping
When a home agent answers on a fallback, I read the HTTP status before I touch the model name.
- 401 or 403 authentication error: credential, plan, or region mismatch. Matching pairs. Do not retry it as quota.
- 429 and allocated-quota messages: a different class of failure. Rotating keys for rate-limit phrases will not unstick a rejected credential, and a rejected credential will not be retried as if it were a 429.
- A configured default can survive a turn that used a fallback. Check unavailable auth profiles before you "fix" the default.
I did not need a new model. I needed to stop treating "who answered" as "what is configured."
The default can still be Qwen. The answer can still be someone else. The status code is the part that tells you which story you are in.


