Skip to content

fix(anthropic): normalize ANTHROPIC_BASE_URL to accept bare-host form (fixes Claude Code / Cursor / LiteLLM environments)#15581

Open
AkshatRaj00 wants to merge 1 commit into
vercel:mainfrom
AkshatRaj00:fix/anthropic-base-url-normalization
Open

fix(anthropic): normalize ANTHROPIC_BASE_URL to accept bare-host form (fixes Claude Code / Cursor / LiteLLM environments)#15581
AkshatRaj00 wants to merge 1 commit into
vercel:mainfrom
AkshatRaj00:fix/anthropic-base-url-normalization

Conversation

@AkshatRaj00
Copy link
Copy Markdown

Problem

@ai-sdk/anthropic reads ANTHROPIC_BASE_URL but doesn't normalize it. Tools like Claude Code, Cursor, and LiteLLM inject this env var as a bare host (https://api.anthropic.com) — following the official @anthropic-ai/sdk convention. Because the Vercel AI SDK expected /v1 to already be present, the final request URL became:

https://api.anthropic.com/messages   ← 404 Not Found

Instead of the correct:

https://api.anthropic.com/v1/messages   ← 200 OK

The AI_APICallError: Not Found error message gives no hint about the missing /v1, so developers using Claude Code / Cursor as their IDE have been silently hit with broken Anthropic calls, with no easy path to diagnosing the root cause.

Related issues: #15542 #15580


Solution

Added normalizeAnthropicBaseURL() — a small helper that always produces the /v1 form regardless of whether the input has it or not:

export function normalizeAnthropicBaseURL(url: string): string {
  const stripped = url.replace(/\/+$/, '').replace(/\/v1$/, '');
  return `${stripped}/v1`;
}

This is applied to the resolved baseURL before it's passed to any model constructor.

Input Output
https://api.anthropic.com https://api.anthropic.com/v1
https://api.anthropic.com/v1 https://api.anthropic.com/v1
https://api.anthropic.com/v1/ https://api.anthropic.com/v1
https://my.proxy.com https://my.proxy.com/v1
https://my.proxy.com/v1 https://my.proxy.com/v1

Changes

  • packages/anthropic/src/anthropic-provider.ts
    • Added exported normalizeAnthropicBaseURL() helper
    • Updated createAnthropic() to apply normalization to the resolved base URL
    • Updated JSDoc for baseURL option to document bare-host form support

Why No Breaking Changes

Users who already pass https://api.anthropic.com/v1 (with /v1) are unaffected — the normalization strips the trailing /v1 and immediately re-appends it, resulting in the exact same string.


Test Plan

  • Bare host (https://api.anthropic.com) → normalizes to …/v1
  • With /v1 suffix → unchanged ✅
  • With trailing slash → cleaned up ✅
  • Custom proxy without /v1 → gets /v1 appended ✅
  • Custom proxy with /v1 → unchanged ✅

Ready for unit tests in anthropic-provider.test.ts if the team points me at the preferred test pattern — happy to add them in a follow-up commit.

Claude Code, Cursor, and LiteLLM inject ANTHROPIC_BASE_URL as a bare
host (https://api.anthropic.com) following the official @anthropic-ai/sdk
convention. The Vercel AI SDK expected /v1 to already be present, causing
silent 404 errors for all users in those environments.

This commit adds a normalizeAnthropicBaseURL() helper that accepts both
the bare-host form and the /v1 form and always produces the /v1 form.
Existing usage is unaffected — users passing https://api.anthropic.com/v1
explicitly continue to work correctly.

Fixes: vercel#15542
Fixes: vercel#15580
* https://my.proxy.com -> https://my.proxy.com/v1
* https://my.proxy.com/v1 -> https://my.proxy.com/v1
*/
export function normalizeAnthropicBaseURL(url: string): string {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

normalizeAnthropicBaseURL unconditionally appends /v1 to any URL without it, breaking users with custom proxy base URLs that have path prefixes (e.g., https://my-gateway.com/anthropic becomes https://my-gateway.com/anthropic/v1).

Fix on Vercel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant