{"record":{"id":"f6ebc6048faaf075","repo":"slopus/happy","slug":"happy-session-sessionid-is-missing-resumable-me","errorCode":null,"errorMessage":"Happy session ${sessionId} is missing resumable metadata.","messagePattern":"Happy session (.+?) is missing resumable metadata\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/happy-cli/src/resume/resolveHappySession.ts","lineNumber":41,"sourceCode":"    active: boolean;\n    metadata: string;\n    metadataVersion: number;\n    agentState: string | null;\n    agentStateVersion: number;\n    seq: number;\n    dataEncryptionKey: string | null;\n};\n\ntype RecordEncryption = {\n    key: Uint8Array;\n    variant: 'legacy' | 'dataKey';\n};\n\nexport function parseResumableMetadata(sessionId: string, metadata: unknown): Metadata {\n    try {\n        return ResumableMetadataSchema.parse(metadata) as Metadata;\n    } catch {\n        throw new Error(`Happy session ${sessionId} is missing resumable metadata.`);\n    }\n}\n\nexport type ResumableHappySession = {\n    id: string;\n    active: boolean;\n    metadata: Metadata;\n};\n\nexport type ReconnectableHappySession = ResumableHappySession & {\n    seq: number;\n    metadataVersion: number;\n    agentStateVersion: number;\n    encryptionKey: Uint8Array;\n    encryptionVariant: 'legacy' | 'dataKey';\n};\n\nexport function resolveSessionRecordByPrefix<T extends { id: string }>(records: T[], sessionId: string): T {","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/slopus/happy/blob/b824cd0a4681d41af631a8e422a813873e4455b0/packages/happy-cli/src/resume/resolveHappySession.ts#L23-L59","documentation":"parseResumableMetadata validates decrypted session metadata against ResumableMetadataSchema with Zod; if validation fails it discards the Zod details and throws a generic Error saying the session is missing resumable metadata. The decrypted payload exists but doesn't match the expected shape (required fields like path, flavor, ids missing or wrong-typed).","triggerScenarios":"Calling parseResumableMetadata with metadata that fails ResumableMetadataSchema.parse — raised from fetchServerMetadata, the metadata getter, or decryptSessionMetadata — e.g. metadata encrypted by an older schema version, decryption producing garbage (wrong encryptionKey/variant), or a field renamed between versions.","commonSituations":"Version skew between the CLI that wrote the session and the one resuming it; wrong encryption key or variant yielding malformed plaintext that happens to decode but not validate; server metadata absent/stripped; partially written metadata.","solutions":["Upgrade happy-cli so writer and reader schema versions match, then retry","Confirm the session's encryptionKey/encryptionVariant in the sessions file are correct — bad keys yield unparseable plaintext","Inspect the decrypted metadata to find which schema field is missing or mistyped","Delete the broken session record and start a new session to regenerate valid metadata"],"exampleFix":"// before (old metadata lacking flavor)\n{ path: \"/repo\", claudeSessionId: \"...\" } // fails ResumableMetadataSchema\n// after: upgrade CLI and re-create session\nnpm i -g happy-coder@latest\nhappy  # new session with full metadata\nhappy resume <session-id>","handlingStrategy":"try-catch","validationCode":"import { ResumableMetadataSchema } from './resolveHappySession';\nconst result = ResumableMetadataSchema.safeParse(metadata);\nif (!result.success) {\n  console.error('Metadata failed schema:', result.error.issues);\n  process.exit(1);\n}","typeGuard":"function isResumableMetadata(m: unknown): m is Metadata {\n  return ResumableMetadataSchema.safeParse(m).success;\n}","tryCatchPattern":"try {\n  await handleResumeCommand([sessionId]);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('missing resumable metadata')) {\n    console.error(`${e.message} — likely version skew or bad encryption key; upgrade happy-cli or re-create the session.`);\n    process.exit(1);\n  }\n  throw e;\n}","preventionTips":["Keep happy-cli versions consistent across machines so the schema matches","Use safeParse to surface the exact Zod issues instead of the generic message","Verify encryptionKey/encryptionVariant are correct — wrong keys decrypt into invalid shapes","Drop and recreate sessions with metadata written by obsolete schema versions"],"tags":["zod","schema-validation","metadata","resume"],"backgroundTag":"schema-validation-failed","analyzedSha":"b824cd0a4681d41af631a8e422a813873e4455b0","analyzedAt":"2026-08-31T23:12:36.205Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}