QuantumNous/new-api · error · Error
Failed to refresh credential
Error message
Failed to refresh credential
What it means
Thrown by handleRefreshCodexCredential in the channel drawer when refreshCodexCredential(channelId) returns success=false. It is gated on channelId being set; the backend message or this i18n fallback is toasted, and on success the channels detail query is invalidated.
Source
Thrown at web/src/features/channels/components/drawers/channel-mutate-drawer.tsx:1409
title: t('Verify to view channel key'),
description: t(
'Use Passkey or 2FA to confirm your identity before revealing this channel key.'
),
})
} catch (error) {
if (error instanceof Error) {
toast.error(error.message)
}
}
}, [channelId, withVerification, fetchChannelKey, t])
const handleRefreshCodexCredential = useCallback(async () => {
if (!channelId) return
setIsCodexCredentialRefreshing(true)
try {
const res = await refreshCodexCredential(channelId)
if (!res.success) {
throw new Error(res.message || t('Failed to refresh credential'))
}
toast.success(t('Credential refreshed'))
queryClient.invalidateQueries({
queryKey: channelsQueryKeys.detail(channelId),
})
} catch (error) {
toast.error(error instanceof Error ? error.message : t('Refresh failed'))
} finally {
setIsCodexCredentialRefreshing(false)
}
}, [channelId, queryClient, t])
// Unified function to update models
const updateModels = useCallback(
(newModels: string[], merge: boolean = false) => {
const finalModels = merge
? formatModelsArray([...currentModelsArray, ...newModels])
: formatModelsArray(newModels)View on GitHub (pinned to e2c7aa7b10)
Solutions
- Read the toast — res.message names the upstream reason (invalid_grant, revoked, etc.)
- If the refresh token is revoked/expired, re-create the credential (re-run the auth flow) instead of refreshing
- Confirm backend version supports Codex credential refresh and can reach the upstream token endpoint (proxy)
- Retry after re-login if the underlying failure was a 401 session
Example fix
// before
const res = await refreshCodexCredential(channelId)
if (!res.success) {
throw new Error(res.message || t('Failed to refresh credential'))
}
// after - after a successful refresh also drop cached key state
const res = await refreshCodexCredential(channelId)
if (!res.success) {
throw new Error(res.message || t('Failed to refresh credential'))
}
setChannelKey('') Defensive patterns
Strategy: try-catch
Validate before calling
if (!channelId) return // guard already present
Try / catch
setIsCodexCredentialRefreshing(true)
try {
const res = await refreshCodexCredential(channelId)
if (!res.success) throw new Error(res.message || t('Failed to refresh credential'))
toast.success(t('Credential refreshed'))
queryClient.invalidateQueries({ queryKey: channelsQueryKeys.detail(channelId) })
} catch (error) {
toast.error(error instanceof Error ? error.message : t('Refresh failed'))
} finally {
setIsCodexCredentialRefreshing(false)
} Prevention
- Disable the refresh button while isCodexCredentialRefreshing
- On invalid_grant-style messages, guide re-authorization instead of retry
- Invalidate the channel detail query after success so the UI shows the new credential state
When it happens
Trigger: Clicking refresh credential on a Codex channel whose token refresh fails upstream (refresh token revoked, OAuth flow incomplete, upstream 4xx), or when the request rejects (network/session).
Common situations: Codex/ChatGPT backend credential fully expired so refresh grant no longer works — must re-auth; upstream changed token endpoint; backend deployment lacks the refresh feature; admin session expired.
Related errors
- Failed to fetch usage
- Failed to fetch reset credit details
- Failed to reset usage
- Failed to fetch channel key
- Failed to initialize OAuth
AI-assisted analysis of QuantumNous/new-api@e2c7aa7b10 (2026-08-15).
Data as JSON: /api/errors/31b180212632907a.
Report an issue: GitHub.