{"record":{"id":"0c2a08f79b101a9b","repo":"musistudio/claude-code-router","slug":"issue-message","errorCode":null,"errorMessage":"${issue.message}","messagePattern":"\\$\\{issue\\.message\\}","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/config/config.ts","lineNumber":569,"sourceCode":"      const protocol = parseProviderCapabilityProtocol(\n        readString(capability.type) || readString(capability.protocol)\n      );\n      return Boolean(protocol && protocol !== \"openai_chat_completions\");\n    });\n  });\n}\n\nfunction assertProviderApiKeysAreSafe(config: AppConfig): void {\n  for (const provider of config.Providers ?? []) {\n    const apiKey = providerApiKey(provider);\n    const baseUrl = providerBaseUrl(provider);\n    const issue = providerApiKeySafetyIssue({\n      apiKey,\n      baseUrl,\n      name: provider.name\n    });\n    if (issue) {\n      throw new Error(issue.message);\n    }\n    assertProviderAccountApiKeyTargetsAreSafe(provider, apiKey, baseUrl);\n    for (const credential of provider.credentials ?? []) {\n      const credentialApiKey = providerCredentialApiKey(credential);\n      const credentialIssue = providerApiKeySafetyIssue({\n        apiKey: credentialApiKey,\n        baseUrl,\n        name: provider.name\n      });\n      if (credentialIssue) {\n        throw new Error(credentialIssue.message);\n      }\n      assertProviderCredentialAccountApiKeyTargetsAreSafe(provider, credential, credentialApiKey, baseUrl);\n    }\n  }\n}\n\nfunction assertProviderAccountApiKeyTargetsAreSafe(provider: GatewayProviderConfig, apiKey: string, baseUrl: string): void {","sourceCodeStart":551,"sourceCodeEnd":587,"githubUrl":"https://github.com/musistudio/claude-code-router/blob/99f24806c6a2c660b16e53e95211c517448a6c90/packages/core/src/config/config.ts#L551-L587","documentation":"While saving app config, providerApiKeySafetyIssue flagged the provider's primary apiKey/baseUrl combination as unsafe (e.g. key sent to a disallowed host); the issue's message is rethrown verbatim.","triggerScenarios":"saveAppConfigNow → assertProviderApiKeysAreSafe → providerApiKeySafetyIssue returns an issue for the provider's main credential.","commonSituations":"User points a provider at a custom/localhost/proxy baseUrl that policy forbids, or pastes a key of the wrong provider for the endpoint.","solutions":["Read issue.message for the exact policy violation (usually the baseUrl).","Change the provider's baseUrl to an allowed endpoint or move the key to the matching provider.","Remove/re-enter the offending provider entry."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const issue = providerApiKeySafetyIssue({ apiKey, baseUrl, name });\nif (issue) fixProviderBeforeSave(issue);","typeGuard":"function providerKeyIsSafe(apiKey: string, baseUrl: string): boolean {\n  return !providerApiKeySafetyIssue({ apiKey, baseUrl, name: 'x' });\n}","tryCatchPattern":"catch (e) { if (/api key|unsafe/i.test((e as Error).message)) showProviderSafetyError(e); }","preventionTips":["Run the safety check pre-save to give inline feedback.","Keep keys paired with their official baseUrl."],"tags":["config","api-key","safety","validation"],"backgroundTag":"config-validation-failed","analyzedSha":"99f24806c6a2c660b16e53e95211c517448a6c90","analyzedAt":"2026-08-27T04:11:01.184Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}