{"record":{"id":"ee75e58bc836315d","repo":"coleam00/Archon","slug":"unknown-provider-provider-known-listconne","errorCode":null,"errorMessage":"Unknown provider '${provider}'. Known: ${listConnectableVendors().join(', ')}.","messagePattern":"Unknown provider '(.+?)'\\. Known: (.+?)\\.","errorType":"validation","errorClass":"InvalidProviderKeyError","httpStatus":null,"severity":"error","filePath":"packages/core/src/credentials/connect-service.ts","lineNumber":66,"sourceCode":" * agent-keyed ids (`claude`/`codex`/`copilot`) and stores under the\n * vendor-canonical id. Throws {@link InvalidProviderKeyError} (before any DB\n * write) when the key is blank or the vendor is not in the registry-derived\n * connectable catalog; any other throw is a storage failure. The plaintext key\n * is encrypted inside the store and is never logged.\n */\nexport async function persistProviderApiKey(\n  userId: string,\n  provider: string,\n  apiKey: string,\n  label?: string | null\n): Promise<PersistProviderApiKeyResult> {\n  const trimmedKey = apiKey.trim();\n  if (!trimmedKey) {\n    throw new InvalidProviderKeyError('API key must not be empty.');\n  }\n  const vendor = normalizeCredentialVendor(provider);\n  if (!isConnectableVendor(vendor)) {\n    throw new InvalidProviderKeyError(\n      `Unknown provider '${provider}'. Known: ${listConnectableVendors().join(', ')}.`\n    );\n  }\n  const normalizedLabel = label?.trim() || null;\n  await saveUserProviderKey({\n    userId,\n    provider: vendor,\n    kind: 'api_key',\n    apiKey: trimmedKey,\n    label: normalizedLabel,\n  });\n  // Never log the key value — vendor + user only.\n  getLog().info({ userId, provider: vendor }, 'provider_api_key.persisted');\n  return { provider: vendor, kind: 'api_key', label: normalizedLabel };\n}\n\n/** Secret-free result of a successful subscription (OAuth) connect. */\nexport interface PersistProviderOAuthResult {","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/core/src/credentials/connect-service.ts#L48-L84","documentation":"InvalidProviderKeyError thrown by persistProviderApiKey when the provider id (after legacy-alias normalization) is not an api_key-connectable vendor in the catalog. The service fails fast before encrypting and persisting a key it could never deliver, and lists the currently connectable vendors.","triggerScenarios":"Calling persistProviderApiKey(userId, provider, key) with an unrecognized or non-api-key provider id: a typo ('antropic'), a legacy alias outside {claude, codex, copilot}, an ambient-only vendor (amazon-bedrock), a subscription-only vendor (use persistProviderOAuth instead), or a custom provider that failed to register.","commonSituations":"Migrating from pre-#1955 agent-keyed ids and using an alias that no longer exists; connecting Bedrock/Vertex via API key when those are ambient-detected; provider registry not bootstrapped (registerBuiltinProviders not run) so the catalog is empty.","solutions":["Use one of the vendors listed in the error (call listConnectableVendors() for the current set).","Normalize legacy ids via normalizeCredentialVendor before calling, and use vendor-canonical ids ('anthropic', 'openai', 'github-copilot').","For subscription-only providers (Claude/OpenAI subscriptions), call persistProviderOAuth instead of persistProviderApiKey.","If a legitimately new vendor is rejected, add its env-var rule to PI_PROVIDER_ENV_VARS (see error 191) — this throw means the catalog cannot deliver it.","Ensure provider registration (registerBuiltinProviders/registerCommunityProviders) ran before connect."],"exampleFix":"// before\nawait persistProviderApiKey(userId, 'claude-code', key);\n// after\nawait persistProviderApiKey(userId, 'anthropic', key);","handlingStrategy":"validation","validationCode":"import { isConnectableVendor, normalizeCredentialVendor } from './credentials';\nfunction canConnect(id: string): boolean {\n  return isConnectableVendor(normalizeCredentialVendor(id));\n}","typeGuard":null,"tryCatchPattern":"try {\n  await persistProviderApiKey(userId, provider, key);\n} catch (e) {\n  if (e instanceof InvalidProviderKeyError && e.message.startsWith('Unknown provider')) {\n    // show listConnectableVendors() to the user\n  } else throw e;\n}","preventionTips":["Always pass vendor-canonical ids ('anthropic', 'openai', 'github-copilot'); run normalizeCredentialVendor first.","Populate provider selectors from listConnectableVendors() rather than hardcoding ids.","Use subscription login (persistProviderOAuth) for subscription-only vendors.","Ensure provider registration ran before any connect call in process entrypoints."],"tags":["credentials","api-key","unknown-provider","validation"],"backgroundTag":"unknown-provider","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}