slopus/happy · error
Happy session lookup authentication expired for legacy accou
Error message
Happy session lookup authentication expired for legacy account credentials.
What it means
fetchSessions lists the account's sessions from the Happy API using legacy account credentials. When the API responds with HTTP 401 (the auth token is expired or rejected), it throws this dedicated error instead of the generic network message, signaling that the stored legacy credentials are no longer valid and the user must re-authenticate.
Source
Thrown at packages/happy-cli/src/resume/resolveHappySession.ts:144
throw new Error(`Failed to decrypt metadata for Happy session ${session.id}`);
}
return parseResumableMetadata(session.id, metadata);
}
async function fetchSessions(credentials: LocalHappyAgentCredentials): Promise<RawSession[]> {
try {
const response = await axios.get(`${configuration.serverUrl}/v1/sessions`, {
headers: {
Authorization: `Bearer ${credentials.token}`,
'X-Happy-Client': `cli-coding-session/${configuration.currentCliVersion}`,
},
});
return (response.data as { sessions: RawSession[] }).sessions;
} catch (error) {
if (error instanceof AxiosError) {
if (error.response?.status === 401) {
throw new Error('Happy session lookup authentication expired for legacy account credentials.');
}
throw new Error(`Failed to load Happy sessions: ${error.message}`);
}
throw error;
}
}
export async function resolveHappySession(sessionId: string): Promise<ResumableHappySession> {
const credentials = readAgentCredentials();
const sessions = await fetchSessions(credentials);
const matched = resolveSessionRecordByPrefix(sessions, sessionId);
return {
id: matched.id,
active: matched.active,
metadata: decryptSessionMetadata(matched, credentials),
};
}
View on GitHub (pinned to b824cd0a46)
Solutions
- Re-authenticate (happy auth / login) to obtain fresh credentials, then retry the resume.
- Delete stale local credentials if re-login caches oddly, then log in again.
- Check system clock sync (NTP) if tokens expire immediately after refresh.
- Verify the account hasn't been deauthorized/rotated server-side.
Example fix
// before $ happy resume <session-id> // Happy session lookup authentication expired // after $ happy auth # refresh legacy credentials $ happy resume <session-id>
Defensive patterns
Strategy: retry
Try / catch
try {
const session = await resolveHappySession(id);
} catch (err) {
if ((err as Error).message.includes('authentication expired')) {
await runAuthFlow(); // refresh credentials
return resolveHappySession(id); // single retry after re-auth
}
throw err;
} Prevention
- Refresh credentials proactively before long-running automations.
- Keep system clock synchronized (NTP) to avoid premature JWT expiry.
- Detect 401 centrally and trigger re-auth instead of failing the whole command.
When it happens
Trigger: Calling fetchSessions (via resolveHappySession / happy resume) when the bearer token in the legacy agent credentials has expired or been revoked and the server returns 401.
Common situations: Long-lived machine/credentials not used for weeks; server-side token rotation or session invalidation; password change or account deauthorization on another device; clock skew invalidating JWTs.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Authentication failed
- Server unavailable
- Failed to load Happy sessions: ${error.message}
- Server unavailable
- Failed to logout: ${error instanceof Error ? error.message :
AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31).
Data as JSON: /api/errors/0c81ea3cc1ab3009.
Report an issue: GitHub.