{"record":{"id":"0be8f4100c42ffbd","repo":"chatboxai/chatbox","slug":"invalid-session-entry-entry-path","errorCode":null,"errorMessage":"Invalid session entry: ${entry.path}","messagePattern":"Invalid session entry: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/renderer/packages/backup/import-backup.ts","lineNumber":239,"sourceCode":"    let readBytes = 0\n    await readZipFileEntries(\n      file,\n      async (entry) => {\n        throwIfAborted(options.signal)\n        readBytes += entry.compressedSize ?? entry.uncompressedSize\n        options.onProgress?.({\n          phase: 'reading',\n          current: Math.min(readBytes, file.size),\n          total: file.size,\n          label: entry.path,\n        })\n        const checksum = await sha256Checksum(entry.data)\n        const staged: StagedEntry = { path: entry.path, size: entry.uncompressedSize, checksum }\n        if (isBackupJsonPath(entry.path) && !isBackupSessionPath(entry.path)) {\n          staged.value = parseJson(entry.data, entry.path)\n        } else if (isBackupSessionPath(entry.path)) {\n          const value = parseJson(entry.data, entry.path)\n          if (!isBackupSession(value)) throw new Error(`Invalid session entry: ${entry.path}`)\n          const tempKey = `${tempPrefix}:session:${stagedSessionCount++}`\n          await options.storage.setItemNow(tempKey, value)\n          tempStoreKeys.push(tempKey)\n          staged.tempKey = tempKey\n        } else if (isBackupResourcePath(entry.path)) {\n          const tempKey = `${tempPrefix}:resource:${stagedResourceCount++}`\n          await options.storage.setBlob(tempKey, bytesToBase64(entry.data))\n          tempBlobKeys.push(tempKey)\n          staged.tempKey = tempKey\n        } else {\n          throw new Error(`Unsupported backup entry: ${entry.path}`)\n        }\n        stagedEntries.set(entry.path, staged)\n      },\n      {\n        signal: options.signal,\n        entryLimits: (path) => ({ maxEntryUncompressedBytes: backupEntryByteLimit(path) }),\n      }","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/chatboxai/chatbox/blob/81571269addb6bafb589a920b2883f1e1e084fd1/src/renderer/packages/backup/import-backup.ts#L221-L257","documentation":"Thrown during the reading phase when a session.json entry parses as JSON but fails isBackupSession - the value must be an object with a non-empty string id, a string name, and an array messages. Propagates after rollback (commitStarted is false, so only temps are cleaned).","triggerScenarios":"entry.path matches ^sessions/[^/]+/session.json$, the bytes parse as JSON, but the result lacks a valid id/name or messages is not an array.","commonSituations":"A backup from a future/incompatible version whose session schema dropped a required field; a tampered or corrupted session.json; a partially written session from a crashed export.","solutions":["Re-create the backup with a compatible app version.","If the session is salvageable, repair its JSON to include a non-empty string id, string name, and array messages before importing.","Remove the offending session.json and its manifest entry if you accept losing that conversation.","Report the schema mismatch with the source and target app versions."],"exampleFix":"// before: malformed session.json aborts the whole import\nawait importBackupArchive(file, options)\n// after: pre-validate each staged session with the same guard\nimport { isBackupSession } from './archive-layout'\nfor (const [path, value] of parsedSessions) {\n  if (!isBackupSession(value)) throw new Error('Bad session at ' + path)\n}","handlingStrategy":"type-guard","validationCode":"// Before import, validate every staged session.json with the same guard used internally.\nimport { isBackupSession } from './archive-layout'\nfor (const [path, value] of parsedSessions) {\n  if (!isBackupSession(value)) throw new Error('Invalid session entry: ' + path)\n}","typeGuard":"import { isBackupSession } from './archive-layout'\nimport type { Session } from '@shared/types'\n// Narrows an unknown parsed value to Session; identical predicate to the one\n// inside importBackupArchive that raises this error.\nconst isValidSessionEntry = (value: unknown): value is Session => isBackupSession(value)","tryCatchPattern":"try {\n  await importBackupArchive(file, options)\n} catch (error) {\n  if (error instanceof Error && error.message.startsWith('Invalid session entry')) {\n    // Repair or remove the offending session.json, then re-import.\n    throw new Error('Archive contains a malformed session', { cause: error })\n  }\n  throw error\n}","preventionTips":["Only import backups produced by a compatible app version.","If repairing by hand, ensure each session.json has a non-empty string id, string name, and array messages.","Validate staged sessions with isBackupSession before handing the archive to the importer."],"tags":["backup","import","session","schema","validation"],"backgroundTag":null,"analyzedSha":"81571269addb6bafb589a920b2883f1e1e084fd1","analyzedAt":"2026-08-12T21:51:44.981Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}