Skip to content

Claude Code Custom ANTHROPIC_BASE_URL Errors: 404s, Auth Conflicts and Fixes ​

You pointed Claude Code at a gateway with ANTHROPIC_BASE_URL, and now every prompt fails with a model error, Invalid API key, an unexpected login prompt, or a warning about two credentials. Almost every case comes down to one of five config mistakes.

Quick answer

Claude Code appends /v1/messages to ANTHROPIC_BASE_URL on its own, so set it to the bare origin (https://byesu.com, with no /v1 and no trailing slash). Put the gateway token in one variable, normally ANTHROPIC_AUTH_TOKEN, and unset any leftover ANTHROPIC_API_KEY. Claude Code reads shell exports only at startup, so restart it after a change, then run /status to see the base URL and credential it is actually using.

Symptoms and What They Mean ​

What you seeMost likely causeFix
There's an issue with the selected model (claude-...). It may not exist or you may not have access to it. Run /model to pick a different model.Base URL ends in /v1, so requests go to /v1/v1/messages and get a 404, or the model ID is wrongFix 1, Fix 5
Invalid API key · Fix external API key (older versions: Invalid API key · Please run /login)The ANTHROPIC_API_KEY value was rejected, or contains a character HTTP headers can't carryFix 3
Please run /login · API Error: 401 Invalid authentication credentialsThe gateway rejected the credential. Behind a custom base URL, the text after 401 comes from the gatewayFix 2, Fix 3
A startup warning naming two credential sources and ending in auth may not work as expected (older: Auth conflict: Both a token (SOURCE) and an API key (SOURCE) are set)A gateway credential and a saved claude.ai login are both activeFix 2
Not logged in · Please run /login, or the claude.ai sign-in screenNo credential reached the sessionFix 4
Connection refused — a firewall or proxy may be blocking it (ConnectionRefused)A leftover ANTHROPIC_BASE_URL points at a proxy that's no longer running, or the host is misspelledFix 1

Claude Code reports the doubled-path 404 as a model error, so it's easy to miss. A user in anthropics/claude-code#26408 found it by launching with --debug and searching the log under ~/.claude/debug:

text
[ERROR] API error (attempt 1/11): 404 404 {"error":{"message":"Invalid URL (POST /v1/v1/messages)","type":"invalid_request_error","param":"","code":""}}

The body varies by gateway, but /v1/v1/ in the path confirms it.

Why It Happens ​

  1. Claude Code builds the path itself. Anthropic's gateway compatibility guide says inference requests post to /v1/messages (with ?beta=true) under your ANTHROPIC_BASE_URL. A base URL that already ends in /v1 doubles it.
  2. Each credential variable is sent in a different header, and only one is used. ANTHROPIC_AUTH_TOKEN goes out as Authorization: Bearer, and ANTHROPIC_API_KEY goes out as X-Api-Key. The authentication precedence is cloud-provider credentials, then ANTHROPIC_AUTH_TOKEN, then ANTHROPIC_API_KEY, then apiKeyHelper, then CLAUDE_CODE_OAUTH_TOKEN, with your /login subscription last. If a stale value sits higher in that list, it wins without any warning.

Fix 1: Use the Bare Origin as the Base URL ​

bash
# Wrong: Claude Code appends /v1/messages → /v1/v1/messages → 404
export ANTHROPIC_BASE_URL="https://byesu.com/v1"

# Right
export ANTHROPIC_BASE_URL="https://byesu.com"

Trailing slash: the Anthropic TypeScript SDK collapses https://byesu.com/ + /v1/messages into a single slash, so Claude Code usually tolerates it. Your own curl tests don't get that cleanup and would request //v1/messages, so leave the slash off.

Test the URL and token before opening Claude Code, using the one-token request from Anthropic's gateway setup guide:

bash
curl -sS -w '\n%{http_code}\n' -X POST "$ANTHROPIC_BASE_URL/v1/messages" \
  -H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model": "claude-sonnet-5-5", "max_tokens": 1, "messages": [{"role": "user", "content": "."}]}'

A body starting with {"id":"msg_ means the URL and token both work. An unknown-model error also confirms both, because the gateway authenticated the request before it looked at the model. A path 404 means the base URL is wrong, and a 401 means the credential is wrong.

Connection refused while curl -I https://api.anthropic.com works usually means a leftover ANTHROPIC_BASE_URL. Remove it from your shell profile and from the settings env block, then open a new terminal.

Fix 2: Use Exactly One Credential Variable ​

VariableHeader sentNotes
ANTHROPIC_AUTH_TOKENAuthorization: Bearer …Applies immediately, with no prompt. Anthropic suggests it when a gateway doesn't say which header it expects
ANTHROPIC_API_KEYX-Api-Key: …Interactive mode asks you to approve it once. If you declined it earlier, it is ignored without a prompt; re-enable it under /config → Use custom API key
bash
env | grep ANTHROPIC        # everything your shell passes in
unset ANTHROPIC_API_KEY     # bearer-token gateway: drop the other variable

Mixing them causes confusing 401s: an old ANTHROPIC_AUTH_TOKEN outranks a new ANTHROPIC_API_KEY, and a correct token in the variable whose header the gateway doesn't read never gets accepted.

For the auth-conflict warning, Anthropic's troubleshooting table gives two options: unset the variable to use the saved claude.ai login, or run /logout to keep only the gateway credential. Afterwards, /status should show an Anthropic base URL line and an Auth token or API key line for the credential in use.

Fix 3: Clear "Invalid API key" and 401 ​

Behind a gateway, running /login won't help, because the gateway is the one rejecting the credential. Check these:

  • A stale key from the environment. Anthropic's error reference warns that direnv, dotenv plugins and IDE terminals can load an old key from a project .env without you noticing. Run env | grep ANTHROPIC in the terminal you launch from.
  • Invisible characters. If the message continues past Fix external API key with something like it contains a line break at character 41, the key never left your machine. Re-paste it.
  • The wrong variable, or a dead token. Switch variables and rerun the curl test, then confirm in the gateway console that the token still exists and is enabled.

General 401 causes are covered in Claude API 401 Authentication Error.

Fix 4: Put the Config Where Claude Code Reads It ​

The most reliable place for gateway settings is the env block of ~/.claude/settings.json (on Windows, %USERPROFILE%\.claude\settings.json):

json
{
  "env": {
    "ANTHROPIC_BASE_URL": "https://byesu.com",
    "ANTHROPIC_AUTH_TOKEN": "sk-your-token"
  }
}

According to the environment variables reference:

  • Shell exports are read at startup. After editing ~/.zshrc, open a new terminal and start claude again.
  • The env block is reapplied when you save the file, but removing a variable only takes effect at the next launch. If in doubt, restart.
  • When both are set, the settings file usually wins over a shell export of the same variable.

Common ways the config goes missing:

  • A project's .claude/settings.json. Don't put a token there, since that file gets committed. Most of its env values also wait until you trust the folder, so first-run setup can still show the login screen. Use a shell export or ~/.claude/settings.json instead.
  • The VS Code extension. It reads credentials from claudeCode.environmentVariables in VS Code's own settings.
  • Broken JSON. A trailing comma or a // comment breaks the file and triggers a Settings Error at startup. claude doctor lists what it rejected.

Our Claude Code setup guide also sets "hasCompletedOnboarding": true in ~/.claude.json to skip the claude.ai sign-in screen.

Fix 5: Set Model IDs the Gateway Serves ​

A correct URL and token can still return There's an issue with the selected model if the model ID doesn't exist on the gateway. The relevant variables, from model configuration:

VariableWhat it controls
ANTHROPIC_MODELThe session's model. Overrides the model key in settings files
ANTHROPIC_DEFAULT_MODELThe model new sessions start on, used only when no settings file sets model (v2.1.236+)
ANTHROPIC_DEFAULT_OPUS_MODEL / _SONNET_MODELWhat the opus / sonnet aliases resolve to
ANTHROPIC_DEFAULT_HAIKU_MODELWhat haiku resolves to; also used for background tasks
ANTHROPIC_SMALL_FAST_MODELDeprecated; use ANTHROPIC_DEFAULT_HAIKU_MODEL
json
{
  "env": {
    "ANTHROPIC_BASE_URL": "https://byesu.com",
    "ANTHROPIC_AUTH_TOKEN": "sk-your-token",
    "ANTHROPIC_MODEL": "claude-opus-5-5",
    "ANTHROPIC_DEFAULT_SONNET_MODEL": "claude-sonnet-5-5"
  }
}

Use full model IDs exactly as the gateway lists them. If chat works but background features fail, point ANTHROPIC_DEFAULT_HAIKU_MODEL at a model the gateway does list. CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 fills the /model picker from the gateway's /v1/models. For model-ID spelling problems, see Claude API 404 model not found.

If You're Using byesu ​

byesu is an AI API gateway with Anthropic-native and OpenAI-compatible endpoints. One key covers Claude, GPT, Grok and Gemini, billed pay-as-you-go with no subscription. For Claude Code:

  • Set ANTHROPIC_BASE_URL=https://byesu.com, with no /v1 and no trailing slash. https://byesu.com/v1 is for OpenAI-format clients such as Codex CLI.
  • Put the token in ANTHROPIC_AUTH_TOKEN, and copy model IDs such as claude-opus-5-5 or claude-sonnet-5-5 from the console model list.

To get started, create a token and follow the Quick Start. The full walkthrough, including a one-click setup script, is in Connecting Claude Code CLI.

FAQ ​

Should ANTHROPIC_BASE_URL include /v1? ​

No. Claude Code appends /v1/messages to ANTHROPIC_BASE_URL itself, so a base URL ending in /v1 produces requests to /v1/v1/messages, which a gateway answers with 404. Use the bare origin, for example https://byesu.com, with no /v1 and no trailing slash.

What is the difference between ANTHROPIC_AUTH_TOKEN and ANTHROPIC_API_KEY? ​

ANTHROPIC_AUTH_TOKEN is sent as an Authorization: Bearer header; ANTHROPIC_API_KEY is sent as an X-Api-Key header and, in interactive mode, must be approved once before it is used. When both are set, Claude Code uses ANTHROPIC_AUTH_TOKEN. Set only the one your gateway expects and unset the other.

Why does Claude Code say Invalid API key and ask me to run /login? ​

The credential Claude Code sent was rejected, or no usable credential reached the session. Behind a custom base URL, /login does not fix it: check that the right variable is set, that no stale ANTHROPIC_API_KEY is exported in your shell or loaded from a .env file, and run /status to see which credential is active.

Do I need to restart Claude Code after changing environment variables? ​

For shell exports, yes: Claude Code reads shell variables at startup. Values in the env block of ~/.claude/settings.json are reapplied to a running session when you save the file, but removing a variable only takes effect on the next launch. Restarting is the simplest way to be sure.

Which environment variable sets the model in Claude Code? ​

ANTHROPIC_MODEL sets the session model and overrides the model setting in settings files. ANTHROPIC_DEFAULT_OPUS_MODEL, ANTHROPIC_DEFAULT_SONNET_MODEL and ANTHROPIC_DEFAULT_HAIKU_MODEL control what the opus, sonnet and haiku aliases resolve to; the haiku one is also used for background tasks. Each needs a full model ID your gateway serves.

Got a problem? Contact support or join our group.