{"record":{"id":"cfdc4c8761adbb41","repo":"coleam00/Archon","slug":"vendor-vendor-pi-backend-has-no-env-based-o","errorCode":null,"errorMessage":"Vendor '${vendor}' (Pi backend) has no env-based OAuth delivery; subscriptions reach Pi via auth.json.","messagePattern":"Vendor '(.+?)' \\(Pi backend\\) has no env-based OAuth delivery; subscriptions reach Pi via auth\\.json\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/credentials/delivery.ts","lineNumber":198,"sourceCode":"      return {\n        env: {\n          COPILOT_GITHUB_TOKEN: cred.kind === 'api_key' ? cred.apiKey : cred.oauthApiKey,\n        },\n      };\n\n    default: {\n      // Happy path first: any vendor in the generated env map delivers its\n      // API key. This includes google-vertex, which is BOTH api_key-capable\n      // and ambient — a stored Vertex key must deliver, so the env lookup\n      // 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  }","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/core/src/credentials/delivery.ts#L180-L216","documentation":"Thrown by deliverCredential when it resolves an oauth-kind stored credential for a vendor that maps to a Pi backend env var. Pi backends consume subscriptions through the aggregate auth.json (buildPiAuthJson), not per-vendor env delivery, so an oauth row on that path indicates a connect-layer bug: oauth rows should only exist for anthropic/openai/github-copilot.","triggerScenarios":"deliverCredential(vendor, { kind: 'oauth', ... }) where the vendor has a piEnvVar — caused by an oauth credential row stored under a Pi-backend vendor id, bypassing connect-time guards (e.g. hand-inserted DB rows, a migration, or a code path that stores OAuth blobs for arbitrary vendors).","commonSituations":"Directly manipulating the credentials table; a custom integration storing OAuth output from a non-subscription provider; a regression in connect guards letting an oauth row land under a Pi-backend id.","solutions":["Remove or correct the stored oauth row for that vendor — connect only allows oauth for anthropic/openai/github-copilot.","Reconnect the provider through the supported path (subscription login for supported vendors, API key otherwise).","If this is a Pi-backend provider, ensure Pi receives subscriptions via buildPiAuthJson/auth.json, not an env-delivered oauth credential.","Audit for code paths that persist OAuth blobs without the connect-time SUBSCRIPTION_PROVIDERS guard."],"exampleFix":"// before (row exists: vendor='groq', kind='oauth')\ndeliverCredential('groq', oauthCred); // throws\n// after\ndeliverCredential('groq', { kind: 'api_key', apiKey });","handlingStrategy":"validation","validationCode":"const OAUTH_ALLOWED = new Set(['anthropic', 'openai', 'github-copilot']);\nfunction canStoreOAuth(vendor: string): boolean {\n  return OAUTH_ALLOWED.has(normalizeCredentialVendor(vendor));\n}","typeGuard":null,"tryCatchPattern":"try {\n  const r = deliverCredential(vendor, cred);\n} catch (e) {\n  if ((e as Error).message.includes('no env-based OAuth delivery')) {\n    // the stored row is invalid: flag for reconnect, never retry as-is\n  } else throw e;\n}","preventionTips":["Only persist OAuth blobs through persistProviderOAuth, which enforces SUBSCRIPTION_PROVIDERS.","Never insert credential rows into the DB directly in scripts or migrations.","Assert credential kind matches the vendor's allowed kinds before saving.","Treat this error as a data-corruption signal: reconnect the provider, don't work around delivery."],"tags":["credentials","oauth","delivery","invariant"],"backgroundTag":"oauth-credential-unsupported","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}