coleam00/Archon · error · InvalidProviderKeyError

Unknown provider '${provider}'. Known: ${listConnectableVend

Error message

Unknown provider '${provider}'. Known: ${listConnectableVendors().join(', ')}.

What it means

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.

Source

Thrown at packages/core/src/credentials/connect-service.ts:66

 * agent-keyed ids (`claude`/`codex`/`copilot`) and stores under the
 * vendor-canonical id. Throws {@link InvalidProviderKeyError} (before any DB
 * write) when the key is blank or the vendor is not in the registry-derived
 * connectable catalog; any other throw is a storage failure. The plaintext key
 * is encrypted inside the store and is never logged.
 */
export async function persistProviderApiKey(
  userId: string,
  provider: string,
  apiKey: string,
  label?: string | null
): Promise<PersistProviderApiKeyResult> {
  const trimmedKey = apiKey.trim();
  if (!trimmedKey) {
    throw new InvalidProviderKeyError('API key must not be empty.');
  }
  const vendor = normalizeCredentialVendor(provider);
  if (!isConnectableVendor(vendor)) {
    throw new InvalidProviderKeyError(
      `Unknown provider '${provider}'. Known: ${listConnectableVendors().join(', ')}.`
    );
  }
  const normalizedLabel = label?.trim() || null;
  await saveUserProviderKey({
    userId,
    provider: vendor,
    kind: 'api_key',
    apiKey: trimmedKey,
    label: normalizedLabel,
  });
  // Never log the key value — vendor + user only.
  getLog().info({ userId, provider: vendor }, 'provider_api_key.persisted');
  return { provider: vendor, kind: 'api_key', label: normalizedLabel };
}

/** Secret-free result of a successful subscription (OAuth) connect. */
export interface PersistProviderOAuthResult {

View on GitHub (pinned to 0773b97458)

Solutions

  1. Use one of the vendors listed in the error (call listConnectableVendors() for the current set).
  2. Normalize legacy ids via normalizeCredentialVendor before calling, and use vendor-canonical ids ('anthropic', 'openai', 'github-copilot').
  3. For subscription-only providers (Claude/OpenAI subscriptions), call persistProviderOAuth instead of persistProviderApiKey.
  4. 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.
  5. Ensure provider registration (registerBuiltinProviders/registerCommunityProviders) ran before connect.

Example fix

// before
await persistProviderApiKey(userId, 'claude-code', key);
// after
await persistProviderApiKey(userId, 'anthropic', key);
Defensive patterns

Strategy: validation

Validate before calling

import { isConnectableVendor, normalizeCredentialVendor } from './credentials';
function canConnect(id: string): boolean {
  return isConnectableVendor(normalizeCredentialVendor(id));
}

Try / catch

try {
  await persistProviderApiKey(userId, provider, key);
} catch (e) {
  if (e instanceof InvalidProviderKeyError && e.message.startsWith('Unknown provider')) {
    // show listConnectableVendors() to the user
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01). Data as JSON: /api/errors/ee75e58bc836315d. Report an issue: GitHub.