Gateway model discovery never fires when using apiKeyHelper (works with ANTHROPIC_AUTH_TOKEN)
Version: 2.1.220
Config:
ANTHROPIC_BASE_URL=https://litellm-rnd-prod.internalk.com
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1
apiKeyHelper=<script that outputs a bearer token>
No CLAUDE_CODE_USE_* vars set. Base URL is not api.anthropic.com.
Expected (per https://code.claude.com/docs/en/llm-gateway-protocol#model-discovery):
On startup, GET {ANTHROPIC_BASE_URL}/v1/models?limit=1000 should fire, cache to ~/.claude/cache/gateway-models.json, and populate the /model picker with "From gateway" entries.
Actual (with only apiKeyHelper set, no ANTHROPIC_AUTH_TOKEN):
~/.claude/cache/gateway-models.jsonnever created, across multiple fresh interactive sessions.--debuglog shows zero occurrences ofgatewayDiscovery,models?limit, or any request to/v1/models— the discovery code path never logs anything at all, success or failure.- Manually replaying the exact documented request (
GET {base}/v1/models?limit=1000,x-api-key: <apiKeyHelper output>,anthropic-version: 2023-06-01) against the same proxy returns a clean200with validclaude-*model IDs matching the discovery response schema. /statusshowsAuth token: apiKeyHelperwith no error — credential resolution is healthy and used successfully for real inference requests in the same session.- Pre-warming the apiKeyHelper token in the shell before launching
claudedoes not change the outcome.
Workaround that fixes it:
Exporting ANTHROPIC_AUTH_TOKEN directly before launch makes discovery work immediately:
export ANTHROPIC_AUTH_TOKEN=$(bash /path/to/token-script.sh)
claude --debug
Result: [gatewayDiscovery] cached 6 models logged, ~/.claude/cache/gateway-models.json populated correctly, /model picker shows gateway entries.
Conclusion:
All documented gate conditions (firstParty mode, non-Anthropic base URL, discovery flag set, resolvable credential) are satisfied in both cases. The only difference is synchronous (ANTHROPIC_AUTH_TOKEN) vs. asynchronous (apiKeyHelper, which spawns a subprocess) credential resolution. This strongly suggests the gateway-discovery step runs very early in startup and checks for a credential synchronously, before apiKeyHelper's async resolution has completed/cached — even though that same resolution is ready moments later for the first real inference request. The discovery step also fails completely silently in this case (no log line for skip, fetch, or error), which made this hard to diagnose.
Suggested fix: either await credential resolution (including apiKeyHelper) before running gateway discovery, or log an explicit skip reason when discovery aborts due to missing credential, matching the other skip paths ([Bootstrap] Skipped: ...).
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗