{"record":{"id":"39022da29236a548","repo":"coleam00/Archon","slug":"vendor-vendor-uses-ambient-cloud-credentials","errorCode":null,"errorMessage":"Vendor '${vendor}' uses ambient cloud credentials and has no stored-credential delivery.","messagePattern":"Vendor '(.+?)' uses ambient cloud credentials and has no stored-credential delivery\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/credentials/delivery.ts","lineNumber":208,"sourceCode":"      // takes precedence over the ambient check.\n      const piEnvVar = PI_PROVIDER_ENV_VARS[vendor];\n      if (piEnvVar) {\n        if (cred.kind === 'oauth') {\n          // Reached only if an oauth row exists under a Pi-backend id (connect\n          // guards against this — oauth is anthropic/openai/github-copilot\n          // only). The Pi runtime consumes subscriptions via the aggregate\n          // auth.json (buildPiAuthJson), not this per-vendor env path.\n          throw new Error(\n            `Vendor '${vendor}' (Pi backend) has no env-based OAuth delivery; subscriptions reach Pi via auth.json.`\n          );\n        }\n        return { env: { [piEnvVar]: cred.apiKey } };\n      }\n      if (PI_AMBIENT_VENDORS.includes(vendor)) {\n        // Ambient-ONLY vendors (amazon-bedrock — no env var in the map):\n        // chains are detected from the environment, never stored — a stored\n        // row for one is a connect bug.\n        throw new Error(\n          `Vendor '${vendor}' uses ambient cloud credentials and has no stored-credential delivery.`\n        );\n      }\n      throw new Error(\n        `Unknown credential vendor '${vendor}'. Known: ${[...KNOWN_VENDORS].sort().join(', ')}.`\n      );\n    }\n  }\n}\n\n/**\n * A Pi `AuthStorage` `auth.json` entry (see `@earendil-works/pi-coding-agent`\n * `core/auth-storage.d.ts`): an API key or an OAuth blob, keyed by Pi provider id.\n */\ntype PiAuthCredential = { type: 'api_key'; key: string } | ({ type: 'oauth' } & OAuthCredentials);\n\n/** Relative path (under the per-run artifacts dir) for the generated Pi auth.json. */\nexport { PI_AUTH_JSON_RELATIVE_PATH };","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/core/src/credentials/delivery.ts#L190-L226","documentation":"Thrown by deliverCredential when a stored credential row targets a vendor in PI_AMBIENT_VENDORS (e.g. amazon-bedrock) that is detected from the environment and has no env-var delivery rule. Ambient-only vendors are never connectable and never stored, so a stored row means something wrote one incorrectly — the delivery layer refuses rather than silently dropping the credential.","triggerScenarios":"deliverCredential(vendor, cred) where vendor is ambient-only (amazon-bedrock) and a stored api_key/oauth row exists — from bypassing connect-time isConnectableVendor validation, hand-inserted DB rows, or a vendor reclassified as ambient while old rows remain.","commonSituations":"Trying to store an AWS Bedrock key as a per-user credential instead of configuring AWS chains (AWS_PROFILE / AWS_ACCESS_KEY_ID etc.) in the server environment; stale rows left after a vendor moved to ambient-only.","solutions":["Delete the stored credential row for the ambient vendor; it can never be delivered.","Configure the vendor in the server environment instead (AWS_PROFILE or AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY for Bedrock; GOOGLE_APPLICATION_CREDENTIALS + project/location for Vertex).","Route connect calls through persistProviderApiKey, whose isConnectableVendor guard rejects ambient vendors up front.","If a legit vendor is hitting this, it was likely misclassified — check its presence in PI_PROVIDER_ENV_VARS."],"exampleFix":"// before\nawait saveUserProviderKey({ userId, provider: 'amazon-bedrock', key });\n// after: configure env instead\nprocess.env.AWS_PROFILE = 'my-profile'; // ambient detection handles the rest","handlingStrategy":"validation","validationCode":"import { PI_AMBIENT_VENDORS } from '@archon/providers';\nimport { isConnectableVendor, normalizeCredentialVendor } from './credentials';\nfunction shouldStoreCredential(vendor: string): boolean {\n  const v = normalizeCredentialVendor(vendor);\n  return isConnectableVendor(v) && !PI_AMBIENT_VENDORS.includes(v);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const r = deliverCredential(vendor, cred);\n} catch (e) {\n  if ((e as Error).message.includes('ambient cloud credentials')) {\n    // delete the bogus row; rely on ambient env detection instead\n  } else throw e;\n}","preventionTips":["Configure AWS Bedrock via server env (AWS_PROFILE / AWS_ACCESS_KEY_ID), never via stored per-user keys.","Route all credential writes through persistProviderApiKey/persistProviderOAuth, never direct DB writes.","Clean up stale rows when a vendor becomes ambient-only after an upgrade.","Check the agent credential matrix (ambientConfigured) to confirm ambient vendors are detected before assuming a stored key is needed."],"tags":["credentials","delivery","ambient","aws"],"backgroundTag":"ambient-credentials-undeliverable","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}