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

  1. Read the toast — res.message names the upstream reason (invalid_grant, revoked, etc.)
  2. If the refresh token is revoked/expired, re-create the credential (re-run the auth flow) instead of refreshing
  3. Confirm backend version supports Codex credential refresh and can reach the upstream token endpoint (proxy)
  4. 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

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


AI-assisted analysis of QuantumNous/new-api@e2c7aa7b10 (2026-08-15). Data as JSON: /api/errors/31b180212632907a. Report an issue: GitHub.