slopus/happy · error · LocalResumeSessionError

ambiguous|not_found

ambiguous|not_found

Error message

${message}. Only sessions stored in ${configuration.sessionsFile} can be resumed without legacy account credentials.

What it means

When resolveSessionRecordByPrefix throws (session not found by ID/prefix, or the prefix is ambiguous across multiple records), resolveLocalReconnectableSession re-wraps it as LocalResumeSessionError with code 'ambiguous' or 'not_found' and appends a note that only sessions in configuration.sessionsFile are resumable without legacy account credentials.

Source

Thrown at packages/happy-cli/src/resume/localResumeStore.ts:93

export async function resolveLocalReconnectableSession(sessionId: string): Promise<ReconnectableHappySession> {
    const records = Object.entries(readPersistedSessions()).map(([id, session]) => ({
        id,
        ...session,
    }));

    if (records.length === 0) {
        throw new LocalResumeSessionError(
            `Cannot resume Happy session "${sessionId}" on this machine: no local session encryption data found at ${configuration.sessionsFile}. Start a new Happy session on this machine to enable future resumes.`,
            'not_found',
        );
    }

    let matched: PersistedSessionRecord;
    try {
        matched = resolveSessionRecordByPrefix(records, sessionId);
    } catch (error) {
        const message = error instanceof Error ? error.message : `No Happy session found matching "${sessionId}"`;
        throw new LocalResumeSessionError(
            `${message}. Only sessions stored in ${configuration.sessionsFile} can be resumed without legacy account credentials.`,
            message.startsWith('Ambiguous') ? 'ambiguous' : 'not_found',
        );
    }

    const encryptionKey = decodeBase64(matched.encryptionKey);
    let metadata = parseResumableMetadata(matched.id, matched.metadata);
    if (needsFreshMetadata(metadata)) {
        metadata = await fetchServerMetadata(matched.id, encryptionKey, matched.encryptionVariant) ?? metadata;
    }

    return {
        id: matched.id,
        active: false,
        metadata,
        seq: matched.seq,
        metadataVersion: matched.metadataVersion,
        agentStateVersion: matched.agentStateVersion,

View on GitHub (pinned to b824cd0a46)

Solutions

  1. Re-run with a longer, exact session ID to disambiguate a prefix collision
  2. Run `happy sessions` (or list persisted sessions) to copy the correct full ID
  3. Verify the session was started on this machine and stored in configuration.sessionsFile; otherwise start/seed locally
  4. Authenticate with legacy account credentials if the session predates local-only resume support

Example fix

// before
happy resume ab  // Ambiguous: matches abc123, abcd
// after
happy resume abc123
Defensive patterns

Strategy: validation

Validate before calling

const records = readPersistedSessions();
const matches = Object.keys(records).filter(id => id === sessionId || id.startsWith(sessionId));
if (matches.length === 0) {
  console.error(`No local session matching "${sessionId}"; run happy sessions to list IDs.`);
  process.exit(1);
}
if (matches.length > 1) {
  console.error(`Ambiguous prefix "${sessionId}" matches: ${matches.join(', ')}`);
  process.exit(1);
}

Try / catch

try {
  await handleResumeCommand([sessionId]);
} catch (e) {
  if (e instanceof LocalResumeSessionError && (e.code === 'ambiguous' || e.code === 'not_found')) {
    console.error(e.message);
    process.exit(1);
  }
  throw e;
}

Prevention

When it happens

Trigger: Running `happy resume <id>` where the ID/prefix matches no record, or matches multiple records in the sessions file (resolveSessionRecordByPrefix raises 'Ambiguous...'), or the session exists server-side but was never persisted in the local sessions file.

Common situations: Typo'd or stale session ID; resuming a session created under a legacy account on another machine; a prefix that matches several sessions (e.g. 'abc' matching 'abc123' and 'abcd'); sessions file not synced to this machine.

Related errors


AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31). Data as JSON: /api/errors/e0f7c4a08c7a965f. Report an issue: GitHub.