can1357/oh-my-pi · error

The pinned security OAuth credential could not be resolved

Error message

The pinned security OAuth credential could not be resolved

What it means

resolveExactSecurityOAuthAccess() got a resolution object from getOAuthAccessByCredentialId but with ok:false — the credential exists yet its access token could not be produced (typically a failed refresh). The function narrows the union and throws so callers only ever receive a valid access resolution.

Source

Thrown at packages/coding-agent/src/security/auth.ts:69

		);
	}
	const account: SecurityAccountRef = { provider, credentialId: selected.credentialId };
	if (selected.accountId !== undefined) account.accountId = selected.accountId;
	if (selected.email !== undefined) account.email = selected.email;
	if (selected.orgId !== undefined) account.organizationId = selected.orgId;
	if (selected.orgName !== undefined) account.organizationName = selected.orgName;
	return account;
}

export async function resolveExactSecurityOAuthAccess(
	authStorage: AuthStorage,
	account: SecurityAccountRef,
	options: { forceRefresh: boolean; signal?: AbortSignal },
): Promise<Extract<OAuthAccessResolution, { ok: true }>> {
	const resolution = await authStorage.getOAuthAccessByCredentialId(account.provider, account.credentialId, options);
	if (!resolution) throw new Error("The pinned security OAuth credential is unavailable");
	assertSecurityIdentityMatches(account, resolution);
	if (!resolution.ok) throw new Error("The pinned security OAuth credential could not be resolved");
	return resolution;
}

/**
 * Build a request credential resolver pinned to one durable OAuth row.
 *
 * Initial resolution and refresh both target the same row. The auth driver's
 * final sibling-rotation step returns `undefined`, so an unavailable account
 * fails the scan rather than crossing an account/workspace boundary.
 */
export function createExactSecurityOAuthResolver(
	options: ExactSecurityOAuthOptions,
): NonNullable<AgentOptions["getApiKey"]> {
	const { account, authStorage } = options;
	return model => {
		if (model.provider !== account.provider) {
			throw new Error("Security scan authentication provider mismatch");
		}

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-run authentication for the provider to store fresh tokens
  2. Delete the broken credential and log in again
  3. Check provider token endpoint health/network if refresh fails transiently
  4. Retry with forceRefresh: true to force a token refresh attempt

Example fix

// before
const access = await resolveExactSecurityOAuthAccess(storage, account, { forceRefresh: false });
// after
try {
  const access = await resolveExactSecurityOAuthAccess(storage, account, { forceRefresh: true });
} catch {
  await reauthenticate(provider); // refresh token dead; re-login
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const access = await resolveExactSecurityOAuthAccess(storage, account, { forceRefresh: true });
} catch (err) {
  if (err.message.includes("could not be resolved")) {
    // refresh token dead: trigger interactive re-auth, then retry once
    await reauthenticate(account.provider);
  } else throw err;
}

Prevention

When it happens

Trigger: The stored refresh token is expired/revoked so AuthStorage cannot mint a new access token (even with forceRefresh), or the provider rejects the refresh request during getOAuthAccessByCredentialId.

Common situations: Long-idle credentials whose refresh token expired; provider-side session revocation (password change, sign-out-everywhere); clock skew invalidating tokens.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/415254065516ade0. Report an issue: GitHub.