can1357/oh-my-pi · error · AIError.OAuthError
OAuth provider "${provider}" does not support token refresh
Error message
OAuth provider "${provider}" does not support token refresh What it means
When refreshing via a runtime-registered custom OAuth provider, the library checks customProvider.refreshToken. If the provider is registered but has no refreshToken implementation, token refresh cannot proceed and the library throws AIError.OAuthError with kind 'configuration'. This is a provider-registration gap, not a network or token problem.
Source
Thrown at packages/ai/src/auth-storage.ts:5289
async #requestOAuthCredentialRefresh(
provider: Provider,
credential: OAuthCredential,
credentialId: number | undefined,
signal?: AbortSignal,
): Promise<OAuthCredentials> {
let refreshPromise: Promise<OAuthCredentials>;
// Caller override > store-level hook > local per-provider refresh.
// `RemoteAuthCredentialStore` exposes the hook so a broker-backed gateway
// routes refresh through the broker without explicit wiring.
const storeRefresh = this.#store.refreshOAuthCredential?.bind(this.#store);
const overrideRefresh = this.#refreshOAuthCredentialOverride ?? storeRefresh;
if (overrideRefresh && credentialId !== undefined) {
refreshPromise = overrideRefresh(provider, credentialId, credential, signal);
} else {
const customProvider = getOAuthProvider(provider);
if (customProvider) {
if (!customProvider.refreshToken) {
throw new AIError.OAuthError(`OAuth provider "${provider}" does not support token refresh`, {
kind: "configuration",
provider,
});
}
refreshPromise = customProvider.refreshToken(credential, signal);
} else {
refreshPromise = refreshOAuthToken(provider as OAuthProvider, credential, signal);
}
}
// Bound the refresh so a slow/hanging token endpoint cannot stall credential selection.
// Caller-driven abort jumps the gun on the timeout — the agent's ESC must
// take priority over the floor timeout.
const cancellation = Promise.withResolvers<never>();
let onAbort: (() => void) | undefined;
const timeout = setTimeout(
() =>
cancellation.reject(
new AIError.OAuthError(`OAuth token refresh timed out for provider: ${provider}`, {View on GitHub (pinned to 9690622007)
Solutions
- Add a refreshToken implementation to your custom OAuth provider registration
- If the provider cannot refresh, plan for re-login when the access token expires instead of forcing refresh
- Pass overrideRefresh (a provider-capable refresh function) when triggering refresh for this credential
- Verify the correct provider id — a builtin provider with refresh support may be shadowed by an incomplete custom registration of the same id
Example fix
// before
registerOAuthProvider({ id: "myprov", login: loginFlow }); // no refreshToken
// after
registerOAuthProvider({
id: "myprov",
login: loginFlow,
refreshToken: async (credential, signal) => refreshViaProvider(credential.refresh, signal),
}); Defensive patterns
Strategy: validation
Validate before calling
const custom = getOAuthProvider(provider);
if (custom && !custom.refreshToken) {
throw new Error(`${provider} lacks refreshToken; schedule re-login instead`);
} Try / catch
try {
return await getCredentialWithRefresh(provider);
} catch (error) {
if (error instanceof AIError.OAuthError && error.kind === "configuration") {
await reLogin(provider); // cannot refresh; log in again
}
throw error;
} Prevention
- Always implement refreshToken when registering a custom OAuth provider with expiring tokens
- Unit-test refresh for every registered provider
- Don't shadow builtin provider ids with incomplete custom registrations
When it happens
Trigger: A stored OAuth credential for a custom (runtime-registered) provider expires and the library attempts refresh, but getOAuthProvider(provider).refreshToken is undefined — the provider was registered with login only, or with refresh support removed.
Common situations: Custom provider registered without a refreshToken function; forcing a refresh (overrideRefresh absent, credentialId present) on a provider that only supports initial login; upstream changed the provider registration and dropped refresh support.
Related errors
- Antigravity credentials missing projectId
- Google Cloud credentials missing projectId
- Unknown OAuth provider: ${provider}
- OAuth refresh did not produce a usable credential for provid
- Alibaba Coding Plan
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/54c30017f64e1817.
Report an issue: GitHub.