{"record":{"id":"f30fe75f61044ccd","repo":"mastra-ai/mastra","slug":"anthropic-api-key-credential-is-configured-but-oa","errorCode":null,"errorMessage":"Anthropic API key credential is configured, but OAuth is required.","messagePattern":"Anthropic API key credential is configured, but OAuth is required\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/sdk/src/providers/claude-max.ts","lineNumber":253,"sourceCode":"\n      return params;\n    },\n  };\n}\n\n/**\n * Build a fetch function that handles Anthropic OAuth.\n * Preserves non-auth headers from init (critical for gateway auth header to survive\n * when used with the gateway). Strips `authorization` and `x-api-key`.\n */\nexport function buildAnthropicOAuthFetch(opts: { authStorage?: CredentialStore } = {}): typeof fetch {\n  return (async (url: string | URL | Request, init?: Parameters<typeof fetch>[1]) => {\n    const storage = opts.authStorage ?? getAuthStorage();\n    storage.reload();\n\n    const storedCred = storage.get('anthropic');\n    if (storedCred?.type === 'api_key') {\n      throw new Error('Anthropic API key credential is configured, but OAuth is required.');\n    }\n\n    const accessToken = await storage.getApiKey('anthropic');\n    if (!accessToken) {\n      throw new ProviderAuthRequiredError('Not logged in to Anthropic.');\n    }\n\n    // Preserve existing headers, strip auth-related ones\n    const headers = new Headers();\n    if (init?.headers) {\n      const source =\n        init.headers instanceof Headers\n          ? init.headers\n          : Array.isArray(init.headers)\n            ? new Headers(init.headers as Array<[string, string]>)\n            : new Headers(init.headers as Record<string, string>);\n      source.forEach((value, key) => {\n        const lower = key.toLowerCase();","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/providers/claude-max.ts#L235-L271","documentation":"The Anthropic provider in OAuth (Claude Max/Pro subscription) mode builds a fetch wrapper that reads credentials from the auth storage. If the stored credential is of type 'api_key' but the provider is configured to require OAuth, this hard error is thrown rather than silently falling back. It surfaces a configuration conflict between credential type and auth mode.","triggerScenarios":"Using the claude-max/anthropic OAuth provider path (`anthropic` or `fetchWithOAuth`) while an Anthropic API key was saved via auth storage (e.g. `mastra auth` or login with an API key), or manually placing an api_key credential in storage.","commonSituations":"Developer previously authenticated with a standard Anthropic API key, then switched to Claude Max subscription usage; CI machine has ANTHROPIC_API_KEY persisted into storage; mixing team setups where one member logged in with a key and another with OAuth.","solutions":["Remove the stored api_key credential and log in via OAuth (e.g. `mastra auth login anthropic` / browser OAuth flow)","Or switch the provider configuration to API-key mode instead of the claude-max OAuth provider","Inspect storage with the auth storage API (`storage.get('anthropic')`) to confirm which credential type is present"],"exampleFix":"// before\nstorage.set('anthropic', { type: 'api_key', apiKey: 'sk-ant-...' });\nconst provider = claudeMax(); // requires OAuth\n// after\nstorage.remove?.('anthropic');\nawait loginAnthropicOAuth(); // store { type: 'oauth', ... } then claudeMax() works","handlingStrategy":"validation","validationCode":"const cred = storage.get('anthropic');\nif (cred?.type === 'api_key') {\n  throw new Error('Remove the api_key credential or switch to the API-key provider; OAuth is required.');\n}","typeGuard":"function isOAuthCredential(c: { type: string } | undefined | null): c is { type: 'oauth' } {\n  return c?.type === 'oauth';\n}","tryCatchPattern":"try {\n  await runWithAnthropicOAuth();\n} catch (err) {\n  if (err instanceof Error && err.message.includes('OAuth is required')) {\n    // remove api_key credential and re-login via OAuth\n  } else throw err;\n}","preventionTips":["Keep one auth mode per provider; never mix api_key and OAuth credentials for anthropic","Check credential type with storage.get('anthropic') before initializing the claude-max provider","Script CI auth setup so only the intended credential type is written to storage"],"tags":["auth","oauth","configuration"],"backgroundTag":"oauth-required","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}