ruvnet/ruflo · error · Error
Cognitum auth service returned an unexpected response: ${e.m
Error message
Cognitum auth service returned an unexpected response: ${e.message} What it means
Thrown by refreshAccessToken when the OAuth server is reachable but returns an error that is not a network failure — e.g. invalid_grant (refresh token revoked/expired/reused), a 5xx, or a malformed response body.
Source
Thrown at v3/@claude-flow/cli/src/auth/client.ts:221
* Refreshes an access token. Classifies failure into network-unreachable
* vs. a reachable-but-erroring server so callers can print an honest
* message instead of collapsing both into "offline" (ADR-308 failure
* policy: local ruflo functionality is never affected by auth being
* unavailable, but the diagnostic should say WHY it's unavailable).
*/
export async function refreshAccessToken(refreshTokenValue: string): Promise<OAuthTokenResponse> {
const sec = await loadSecurityOAuth();
try {
return await sec.refreshToken(refreshTokenValue);
} catch (e) {
if (e instanceof sec.OAuthError) {
if (e.code === 'network') {
throw new Error(
'Could not reach the Cognitum auth service. ruflo core functionality is unaffected — ' +
'sign-in is not required for local use.',
);
}
throw new Error(`Cognitum auth service returned an unexpected response: ${e.message}`);
}
throw e;
}
}
/**
* Returns an access token suitable for an authenticated call.
*
* Fast path: a process-memory token with more than one minute remaining.
* Slow path: load the profile's refresh token from the OS keychain, perform
* one refresh, persist a rotated refresh token BEFORE exposing the new access
* token, then update metadata and the process cache. Refresh is deliberately
* demand-driven: offline-safe commands such as plain `auth status` never call
* this function and therefore never create background traffic or retry loops.
*/
export async function getValidAccessToken(profileName = 'default'): Promise<string> {
const profile = getProfile(profileName);
if (!profile) throw new NotLoggedInError(profileName);View on GitHub (pinned to 6b01dc5a68)
Solutions
- Re-authenticate with `ruflo auth login` to obtain a fresh refresh token.
- Check the auth service status page for incidents.
- Avoid running two processes that refresh the same token concurrently.
Defensive patterns
Strategy: try-catch
Type guard
function isAuthServerError(e: unknown): boolean {
return e instanceof Error && /unexpected response|invalid_grant/i.test(e.message);
} Try / catch
try {
return await refreshAccessToken(rt);
} catch (e) {
if (isAuthServerError(e)) {
// prompt the user to re-login; do not auto-retry the spent refresh token
}
throw e;
} Prevention
- Commit rotated refresh tokens before use; never reuse a spent token.
- Serialize refreshes per profile to avoid reuse-detection revocation.
- Surface server error codes verbatim for diagnosis.
When it happens
Trigger: The refresh token was revoked, rotated-and-reused, or expired; the server returned 500/502; the response body was malformed.
Common situations: Refresh token reused after rotation (Cognitum has reuse detection); long-offline machine with an expired token; auth service incident.
Related errors
- state mismatch — the OAuth callback did not match the reques
- login cancelled: no code was entered
- --token-stdin: no input received on stdin
- --token-stdin expects a single JSON object: {"access_token",
- --token-stdin: JSON is missing required field "access_token"
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/ceefc5c5d01a0703.
Report an issue: GitHub.