chatboxai/chatbox · error · Error
Token refresh failed: ${payload.base_resp?.status_msg || tex
Error message
Token refresh failed: ${payload.base_resp?.status_msg || text} What it means
Thrown by MiniMax's refreshToken() when the HTTP response was 2xx but payload.status !== 'success' or payload.access_token is missing. MiniMax returns 200 with a business status field, so this guard catches application-level refresh failures that the HTTP check missed. The message prefers base_resp.status_msg (human-readable MiniMax reason) and falls back to the raw text.
Source
Thrown at src/main/oauth/providers/minimax.ts:229
}).toString(),
})
const text = await response.text()
if (!response.ok) {
log.error(`[OAuth:${config.name}] Token refresh failed:`, text)
throw new Error(`Token refresh failed: ${text}`)
}
const payload = JSON.parse(text || '{}') as {
status?: string
access_token?: string
refresh_token?: string
expired_in?: number
base_resp?: { status_msg?: string }
}
if (payload.status !== 'success' || !payload.access_token) {
throw new Error(`Token refresh failed: ${payload.base_resp?.status_msg || text}`)
}
return {
accessToken: payload.access_token,
refreshToken: payload.refresh_token || credentials.refreshToken,
expiresAt: toExpiresAt(payload.expired_in),
}
},
}
return provider
}
export const minimaxOAuthProvider = createMiniMaxOAuthProvider({
providerId: 'minimax',
name: 'MiniMax Global',
baseUrl: 'https://api.minimax.io',
})View on GitHub (pinned to 81571269ad)
Solutions
- Read base_resp.status_msg — it carries MiniMax's specific reason; treat account/quota messages as requiring re-auth or user action.
- If the response shape changed (status renamed), update the parse to match the current MiniMax contract.
- On business-level 'fail', clear stored credentials and prompt an interactive login rather than retrying the same refresh token.
Example fix
// before
if (payload.status !== 'success' || !payload.access_token) {
throw new Error(`Token refresh failed: ${payload.base_resp?.status_msg || text}`)
}
// after
if (payload.status !== 'success' || !payload.access_token) {
const reason = payload.base_resp?.status_msg || text
log.error('[OAuth:MiniMax] business refresh failure', reason)
if (/invalid|expired|revok/i.test(reason)) throw new ReauthRequiredError(reason)
throw new Error(`Token refresh failed: ${reason}`)
} Defensive patterns
Strategy: try-catch
Type guard
function isMiniMaxBusinessFailure(body: unknown): body is { status: string; base_resp?: { status_msg?: string } } {
return typeof body === 'object' && body !== null && (body as any).status !== 'success'
} Try / catch
try {
return await provider.refreshToken(credentials)
} catch (e) {
const msg = String(e)
if (/invalid|expired|revok|suspend|quota/i.test(msg)) {
await clearStoredCredentials()
throw new ReauthRequiredError(msg)
}
// contract drift: log and surface, do not retry blindly
log.error('MiniMax business refresh failure', msg)
throw e
} Prevention
- Log the parsed payload when status !== 'success' to detect MiniMax contract drift early.
- Treat account-level failures (quota, suspended) as needing user action, not retry.
- On contract drift, update the response type/parser rather than dropping the guard.
When it happens
Trigger: MiniMax returns 200 with status='fail' or a non-zero base_resp.status_code; access_token field absent despite 200; response shape changed and status field is now named differently; refresh token was accepted at transport but rejected at business layer (e.g. quota, account suspended).
Common situations: MiniMax API contract drift (status field renamed); account throttled or suspended returning 200 with an error status_msg; partial response from a load balancer.
Related errors
- MiniMax OAuth failed: ${errorMessage || text}
- Token refresh failed: ${text}
- No refresh token available
- Token refresh failed: ${error}
- Device flow failed: ${raw.error}
AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12).
Data as JSON: /api/errors/1094cc085e3e6414.
Report an issue: GitHub.