slopus/happy · error

No Happy session found matching "${trimmed}"

Error message

No Happy session found matching "${trimmed}"

What it means

After trimming, resolveSessionRecordByPrefix filters the supplied records for IDs starting with the given prefix. If zero records match, it throws this error: the prefix is well-formed but no known Happy session starts with it. The library throws instead of returning null so the CLI can surface a clear lookup failure.

Source

Thrown at packages/happy-cli/src/resume/resolveHappySession.ts:67

};

export type ReconnectableHappySession = ResumableHappySession & {
    seq: number;
    metadataVersion: number;
    agentStateVersion: number;
    encryptionKey: Uint8Array;
    encryptionVariant: 'legacy' | 'dataKey';
};

export function resolveSessionRecordByPrefix<T extends { id: string }>(records: T[], sessionId: string): T {
    const trimmed = sessionId.trim();
    if (!trimmed) {
        throw new Error('Happy session ID is required: happy resume <session-id>');
    }

    const matches = records.filter((record) => record.id.startsWith(trimmed));
    if (matches.length === 0) {
        throw new Error(`No Happy session found matching "${trimmed}"`);
    }
    if (matches.length > 1) {
        throw new Error(`Ambiguous Happy session "${trimmed}" matches ${matches.length} sessions. Be more specific.`);
    }
    return matches[0];
}

function decryptBoxBundle(bundle: Uint8Array, recipientSecretKey: Uint8Array): Uint8Array | null {
    if (bundle.length < 56) {
        return null;
    }

    const ephemeralPublicKey = bundle.slice(0, 32);
    const nonce = bundle.slice(32, 56);
    const ciphertext = bundle.slice(56);
    const decrypted = tweetnacl.box.open(ciphertext, nonce, ephemeralPublicKey, recipientSecretKey);

    return decrypted ? new Uint8Array(decrypted) : null;

View on GitHub (pinned to b824cd0a46)

Solutions

  1. Re-run `happy` to list current sessions and copy the exact ID, then resume with the correct prefix.
  2. Use a longer/complete session ID to rule out partial-copy mistakes.
  3. Verify you are authenticated as the account that owns the session (re-authenticate if needed).
  4. Confirm the session still exists — if it was deleted or rotated, start a new session instead.

Example fix

// before
const session = await resolveHappySession('abc12'); // mistyped prefix
// after
const session = await resolveHappySession('a1b2c3d4-e5f6-7890-abcd-ef1234567890'); // full ID copied from session list
Defensive patterns

Strategy: try-catch

Validate before calling

// Optional pre-check when you already hold the record list:
const exists = records.some(r => r.id.startsWith(prefix));
if (!exists) console.error('No session matches that prefix — list sessions first');

Try / catch

try {
  const session = await resolveHappySession(prefix);
} catch (err) {
  if ((err as Error).message.includes('No Happy session found matching')) {
    // print available sessions and re-prompt for the ID
  } else throw err;
}

Prevention

When it happens

Trigger: Calling resolveSessionRecordByPrefix(records, "abc123") where no record.id in the passed array starts with "abc123" — typically because the session was deleted, the prefix is mistyped, or the records array was fetched from the wrong account.

Common situations: Typos or truncated copy-paste of a session ID; resuming a session created under a different account/machine; the session expired or was purged server-side; stale local cache of sessions.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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