openclaw/openclaw · error · Error
Chutes OAuth credential is missing refresh token
Error message
Chutes OAuth credential is missing refresh token
What it means
Thrown by refreshChutesOAuthCredential when the stored OAuthCredential's refresh field is empty or absent after normalization. This function is called to renew an expired access token; without a refresh_token it cannot perform the grant. This indicates the stored credential is incomplete or corrupted — either it was never granted a refresh token, or it was lost during storage/migration.
Source
Thrown at extensions/chutes/oauth.ts:240
}
return {
access: token.access,
refresh: token.refresh,
expires: token.expires,
email: info?.username,
accountId: info?.sub,
clientId: params.app.clientId,
} as ChutesStoredOAuth;
}
/** Refreshes a stored Chutes OAuth credential through the provider token endpoint. */
export async function refreshChutesOAuthCredential(
credential: OAuthCredential,
options: { fetchFn?: typeof fetch; now?: number } = {},
): Promise<OAuthCredential> {
const refreshToken = normalizeOptionalString(credential.refresh);
if (!refreshToken) {
throw new Error("Chutes OAuth credential is missing refresh token");
}
const clientId = normalizeOptionalString(credential.clientId ?? process.env.CHUTES_CLIENT_ID);
if (!clientId) {
throw new Error("Missing CHUTES_CLIENT_ID for Chutes OAuth refresh (set env var or re-auth).");
}
const clientSecret = normalizeOptionalString(process.env.CHUTES_CLIENT_SECRET);
const body = new URLSearchParams({
grant_type: "refresh_token",
client_id: clientId,
refresh_token: refreshToken,
});
if (clientSecret) {
body.set("client_secret", clientSecret);
}
const token = await requestChutesTokenGrant({
body,View on GitHub (pinned to 01804a7531)
Solutions
- Re-run the Chutes OAuth onboarding flow to obtain a fresh credential with a refresh token
- Inspect the stored credential (auth-profiles.json for the agent) to confirm the refresh field is missing
- If this affects many agents, check whether a migration was supposed to handle old credentials
Defensive patterns
Strategy: try-catch
Validate before calling
function hasValidRefreshCredential(cred: OAuthCredential): boolean {
return typeof cred.refresh === "string" && cred.refresh.trim().length > 0;
}
// Before calling refreshChutesOAuthCredential
if (!hasValidRefreshCredential(storedCred)) {
await reauthenticateChutes(); // trigger fresh onboarding
return;
} Type guard
function hasValidRefreshCredential(cred: OAuthCredential): cred is OAuthCredential & { refresh: string } {
return typeof cred.refresh === "string" && cred.refresh.trim().length > 0;
} Try / catch
try {
const refreshed = await refreshChutesOAuthCredential(credential);
} catch (e) {
if (e instanceof Error && e.message.includes("missing refresh token")) {
// Credential is incomplete; prompt re-authentication
await triggerChutesReauth(agentId);
} else { throw e; }
} Prevention
- Validate stored credentials have refresh_token after onboarding
- Run 'openclaw doctor' after upgrades to detect credential issues
- Keep credential storage migrations tested
When it happens
Trigger: A stored Chutes credential that was created by an older flow that did not persist the refresh token. Credential corruption in the auth-profiles store. Manual credential import that omitted the refresh field. A prior token exchange that did not return a refresh token but was stored anyway (older plugin version before the check at line 645 was added).
Common situations: Upgrading from an older OpenClaw version that stored Chutes credentials differently. Importing credentials from another tool. Storage migration that dropped fields. Corrupt auth-profiles.json after a crash.
Related errors
- Chutes token exchange returned no refresh_token
- Selected Claude CLI OAuth credential is expired or invalid.
- Claude CLI is not authenticated on this host. Run claude aut
- Chutes OAuth redirect hostname must be loopback (got ${hostn
- Paste the full redirect URL (must include code + state).
AI-assisted analysis of openclaw/openclaw@01804a7531 (2026-08-12).
Data as JSON: /api/errors/66b5789bb79e942e.
Report an issue: GitHub.