{"record":{"id":"7410f38171a94946","repo":"can1357/oh-my-pi","slug":"the-pinned-security-oauth-credential-is-unavailabl","errorCode":null,"errorMessage":"The pinned security OAuth credential is unavailable","messagePattern":"The pinned security OAuth credential is unavailable","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/security/auth.ts","lineNumber":67,"sourceCode":"\t\tthrow new Error(\n\t\t\t`Multiple OAuth accounts are available for ${provider}; supply credentialId to pin one exact account`,\n\t\t);\n\t}\n\tconst account: SecurityAccountRef = { provider, credentialId: selected.credentialId };\n\tif (selected.accountId !== undefined) account.accountId = selected.accountId;\n\tif (selected.email !== undefined) account.email = selected.email;\n\tif (selected.orgId !== undefined) account.organizationId = selected.orgId;\n\tif (selected.orgName !== undefined) account.organizationName = selected.orgName;\n\treturn account;\n}\n\nexport async function resolveExactSecurityOAuthAccess(\n\tauthStorage: AuthStorage,\n\taccount: SecurityAccountRef,\n\toptions: { forceRefresh: boolean; signal?: AbortSignal },\n): Promise<Extract<OAuthAccessResolution, { ok: true }>> {\n\tconst resolution = await authStorage.getOAuthAccessByCredentialId(account.provider, account.credentialId, options);\n\tif (!resolution) throw new Error(\"The pinned security OAuth credential is unavailable\");\n\tassertSecurityIdentityMatches(account, resolution);\n\tif (!resolution.ok) throw new Error(\"The pinned security OAuth credential could not be resolved\");\n\treturn resolution;\n}\n\n/**\n * Build a request credential resolver pinned to one durable OAuth row.\n *\n * Initial resolution and refresh both target the same row. The auth driver's\n * final sibling-rotation step returns `undefined`, so an unavailable account\n * fails the scan rather than crossing an account/workspace boundary.\n */\nexport function createExactSecurityOAuthResolver(\n\toptions: ExactSecurityOAuthOptions,\n): NonNullable<AgentOptions[\"getApiKey\"]> {\n\tconst { account, authStorage } = options;\n\treturn model => {\n\t\tif (model.provider !== account.provider) {","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/security/auth.ts#L49-L85","documentation":"resolveExactSecurityOAuthAccess() looks up the pinned credential row via authStorage.getOAuthAccessByCredentialId; when the lookup returns nothing (credential record no longer exists / not visible), it throws this error. It means the SecurityAccountRef points at a credential that is not present at resolution time.","triggerScenarios":"Calling resolveExactSecurityOAuthAccess (or any flow using createExactSecurityOAuthResolver) with a SecurityAccountRef whose credentialId no longer exists in AuthStorage for that provider — e.g. the credential was deleted, logged out, or rotated to a new id between pinning and use.","commonSituations":"Stale credentialId captured earlier in a long-lived config after the user re-authenticated; logout wiped the credential store; running on a machine whose AuthStorage never had that credential.","solutions":["Re-list stored OAuth credentials and re-pin a valid credentialId","Re-authenticate with the provider to recreate the credential","Remove the stale pinned credentialId and let account selection pick a current one"],"exampleFix":"// before\nresolveExactSecurityOAuthAccess(authStorage, { provider: \"openai-codex\", credentialId: \"old-id\" }, opts)\n// after\nconst accounts = listAccounts(authStorage, \"openai-codex\");\nresolveExactSecurityOAuthAccess(authStorage, { provider: \"openai-codex\", credentialId: accounts[0].credentialId }, opts)","handlingStrategy":"validation","validationCode":"const stored = authStorage.listOAuthAccounts(account.provider);\nif (!stored.some(a => a.credentialId === account.credentialId)) {\n  throw new Error(`Credential ${account.credentialId} no longer stored for ${account.provider}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const access = await resolveExactSecurityOAuthAccess(storage, account, opts);\n} catch (err) {\n  if (err.message === \"The pinned security OAuth credential is unavailable\") {\n    await reauthenticate(account.provider); // re-pin fresh credential\n  } else throw err;\n}","preventionTips":["Re-resolve the pinned credentialId at session start instead of persisting it long-term","Re-pin after any logout/re-auth","Verify credential existence before long-running scans"],"tags":["oauth","authentication","stale-credential"],"backgroundTag":"credential-not-found","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}