slopus/happy · error

Happy session ${session.id} is missing its Codex thread ID.

Error message

Happy session ${session.id} is missing its Codex thread ID.

What it means

buildResumeLaunch throws this when a session's resolved flavor is 'codex' but its persisted metadata lacks codexThreadId. Resuming a Codex session requires the original thread ID to pass to `codex --resume <thread-id>`; without it the CLI cannot reconstruct the session.

Source

Thrown at packages/happy-cli/src/resume/handleResumeCommand.ts:59

}

function resolveFlavor(metadata: Metadata): 'codex' | 'claude' | null {
    if (metadata.flavor === 'codex' || metadata.codexThreadId) {
        return 'codex';
    }
    if (metadata.flavor === 'claude' || metadata.claudeSessionId) {
        return 'claude';
    }
    return null;
}

export function buildResumeLaunch(session: ResumableHappySession, options: ResumeLaunchOptions = {}): ResumeLaunch {
    const { metadata } = session;
    const flavor = resolveFlavor(metadata);

    if (flavor === 'codex') {
        if (!metadata.codexThreadId) {
            throw new Error(`Happy session ${session.id} is missing its Codex thread ID.`);
        }
        const args = ['codex', '--resume', metadata.codexThreadId];
        if (options.startedBy) {
            args.push('--started-by', options.startedBy);
        }
        return {
            cwd: metadata.path,
            args,
        };
    }

    if (flavor === 'claude') {
        if (!metadata.claudeSessionId) {
            throw new Error(`Happy session ${session.id} is missing its Claude session ID.`);
        }
        const args = ['claude'];
        if (options.claudeStartingMode) {
            args.push('--happy-starting-mode', options.claudeStartingMode);

View on GitHub (pinned to b824cd0a46)

Solutions

  1. Start a new Happy session with the current CLI version so codexThreadId is captured in metadata
  2. Check that the session was genuinely started with Codex support enabled in the installed happy-cli version
  3. Upgrade happy-cli and re-sync/re-encrypt the session metadata if your version predates codexThreadId
  4. Resume the session manually with `codex --resume <thread-id>` if you can find the thread ID under ~/.codex
Defensive patterns

Strategy: validation

Validate before calling

function canResumeCodex(s: ResumableHappySession): boolean {
  return resolveFlavor(s.metadata) === 'codex' && typeof s.metadata.codexThreadId === 'string' && s.metadata.codexThreadId.length > 0;
}

Type guard

function hasCodexThreadId(m: Metadata): m is Metadata & { codexThreadId: string } {
  return typeof (m as any).codexThreadId === 'string' && (m as any).codexThreadId.length > 0;
}

Try / catch

try {
  const launch = buildResumeLaunch(session);
} catch (e) {
  if (e instanceof Error && e.message.includes('missing its Codex thread ID')) {
    console.error('This Codex session cannot be resumed; start a new session with an up-to-date CLI.');
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling buildResumeLaunch (directly or via handleResumeCommand/launch) with a ResumableHappySession whose metadata.flavor resolves to 'codex' while metadata.codexThreadId is undefined/null — e.g. metadata was written by an older CLI version before Codex support recorded thread IDs.

Common situations: Sessions created before a Codex-supporting happy release; metadata encrypted before codexThreadId was added to ResumableMetadataSchema; hand-edited or partially synced sessions file; session started via a path that never captured the Codex thread ID.

Related errors


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