{"record":{"id":"65d0b54b4fe87aa9","repo":"thedotmack/claude-mem","slug":"auth-invalid","errorCode":"auth_invalid","errorMessage":"Anthropic API key not configured","messagePattern":"Anthropic API key not configured","errorType":"validation","errorClass":"ServerClassifiedProviderError","httpStatus":null,"severity":"critical","filePath":"src/server/generation/providers/ClaudeObservationProvider.ts","lineNumber":47,"sourceCode":"  fetchImpl?: typeof fetch;\n}\n\ninterface AnthropicMessagesResponse {\n  content?: Array<{ type?: string; text?: string }>;\n  usage?: { input_tokens?: number; output_tokens?: number };\n  error?: { type?: string; message?: string };\n}\n\nexport class ClaudeObservationProvider implements ServerGenerationProvider {\n  readonly providerLabel = 'claude' as const;\n  private readonly apiKey: string;\n  private readonly model: string;\n  private readonly maxOutputTokens: number;\n  private readonly fetchImpl: typeof fetch;\n\n  constructor(options: ClaudeObservationProviderOptions) {\n    if (!options.apiKey) {\n      throw new ServerClassifiedProviderError('Anthropic API key not configured', {\n        kind: 'auth_invalid',\n        cause: new Error('apiKey is required'),\n      });\n    }\n    this.apiKey = options.apiKey;\n    this.model = options.model ?? DEFAULT_MODEL;\n    this.maxOutputTokens = options.maxOutputTokens ?? 4096;\n    this.fetchImpl = options.fetchImpl ?? fetch;\n  }\n\n  async generate(\n    context: ServerGenerationContext,\n    signal?: AbortSignal,\n  ): Promise<ServerGenerationResult> {\n    const { prompt, skippedAll } = buildServerGenerationPrompt(context);\n    if (skippedAll) {\n      // All events were scrubbed by privacy stripping. Don't bill the\n      // provider — return a synthetic skip response that parser accepts.","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/server/generation/providers/ClaudeObservationProvider.ts#L29-L65","documentation":"ClaudeObservationProvider's constructor validates that an Anthropic API key was supplied in its options and throws a ServerClassifiedProviderError with kind 'auth_invalid' when it is missing/empty. The provider cannot authenticate to Anthropic without a key, so it fails fast at construction time.","triggerScenarios":"Constructing new ClaudeObservationProvider(options) with options.apiKey undefined, null, or an empty string — typically because ANTHROPIC_API_KEY was not set when server config was built.","commonSituations":"Server started without ANTHROPIC_API_KEY in the environment, key removed from settings, or provider options assembled programmatically without passing the credential through.","solutions":["Set the ANTHROPIC_API_KEY environment variable (or the settings location the server reads it from) and restart the server.","Verify the key is actually propagated into the provider options where ClaudeObservationProvider is constructed.","Catch ServerClassifiedProviderError and check err kind === 'auth_invalid' to give the user a clear configuration prompt instead of a crash."],"exampleFix":"// before\nnew ClaudeObservationProvider({ model: 'claude-sonnet-4' })\n// after\nnew ClaudeObservationProvider({ apiKey: process.env.ANTHROPIC_API_KEY!, model: 'claude-sonnet-4' })","handlingStrategy":"validation","validationCode":"if (!process.env.ANTHROPIC_API_KEY) {\n  throw new Error('ANTHROPIC_API_KEY must be set before starting the server');\n}\nnew ClaudeObservationProvider({ apiKey: process.env.ANTHROPIC_API_KEY });","typeGuard":"const hasApiKey = (o: ClaudeObservationProviderOptions): o is ClaudeObservationProviderOptions & { apiKey: string } =>\n  typeof o.apiKey === 'string' && o.apiKey.length > 0;","tryCatchPattern":"try {\n  provider = new ClaudeObservationProvider(opts);\n} catch (e) {\n  if (e instanceof ServerClassifiedProviderError && e.kind === 'auth_invalid') {\n    console.error('Set ANTHROPIC_API_KEY and restart the server.');\n  }\n}","preventionTips":["Set ANTHROPIC_API_KEY in the server's environment or secret manager before startup.","Fail startup early with a clear message if the key is absent.","Never construct generation providers with possibly-undefined credential fields; validate config at load time."],"tags":["anthropic","api-key","auth","server"],"backgroundTag":"missing-api-key","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}