{"record":{"id":"91bfdccb741116bd","repo":"chatboxai/chatbox","slug":"unsupported-backup-entry-entry-path","errorCode":null,"errorMessage":"Unsupported backup entry: ${entry.path}","messagePattern":"Unsupported backup entry: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/renderer/packages/backup/import-backup.ts","lineNumber":250,"sourceCode":"        })\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      }\n    )\n\n    options.onProgress?.({ phase: 'validating', current: 0, total: 1 })\n    const manifestValue = stagedEntries.get(BACKUP_MANIFEST_PATH)?.value\n    const manifest = BackupManifestSchema.parse(manifestValue)\n    validateManifestEntries(manifest, stagedEntries)\n    const { plans: resourcePlans, resourceKeyMap } = await createResourcePlans(manifest, stagedEntries, options.storage)\n    options.onProgress?.({ phase: 'validating', current: 1, total: 1 })\n\n    const existingStoreKeys = new Set(await options.storage.getAllKeys())\n    const changedKeys = [","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/chatboxai/chatbox/blob/81571269addb6bafb589a920b2883f1e1e084fd1/src/renderer/packages/backup/import-backup.ts#L232-L268","documentation":"Thrown during the reading phase when an archive entry's path matches none of the recognized patterns: manifest/settings/copilots/session-settings JSON, a session.json, or a resource path. The importer refuses unknown content to avoid silently dropping or mis-staging files. Propagates after rollback.","triggerScenarios":"An entry whose path is not classified by isBackupJsonPath, isBackupSessionPath, or isBackupResourcePath reaches the else branch.","commonSituations":"A backup from a newer format that added new entry kinds; a user zipped extra files into the archive; macOS __MACOSX/ metadata or .DS_Store surviving into the zip.","solutions":["Use a backup produced by a compatible app version.","Re-zip the archive excluding foreign files (e.g. __MACOSX, .DS_Store).","If extending the format, update isBackupJsonPath/isBackupResourcePath and the staging switch to recognize the new path.","Strip unknown entries from the zip before importing."],"exampleFix":"// before: stray zip entries abort import\nawait importBackupArchive(file, options)\n// after: filter the archive to only known paths before importing\nconst allowed = (p) =>\n  isBackupJsonPath(p) || isBackupResourcePath(p)\nawait rebuildZipWithout(file, (p) => !allowed(p))\nawait importBackupArchive(cleanedFile, options)","handlingStrategy":"validation","validationCode":"// Reject archives whose entries fall outside recognized path patterns before importing.\nimport { isBackupJsonPath, isBackupResourcePath } from './archive-layout'\nconst recognized = (p: string) => isBackupJsonPath(p) || isBackupResourcePath(p)\nconst unknown = zipEntryPaths.filter((p) => !recognized(p))\nif (unknown.length) throw new Error('Unrecognized entries: ' + unknown.join(', '))","typeGuard":"// True when an entry path is classified as JSON or resource by the layout helpers.\nconst entryPathIsRecognized = (path: string): boolean =>\n  isBackupJsonPath(path) || isBackupResourcePath(path)","tryCatchPattern":"try {\n  await importBackupArchive(file, options)\n} catch (error) {\n  if (error instanceof Error && error.message.startsWith('Unsupported backup entry')) {\n    // Re-zip without foreign files or use a compatible backup.\n    throw new Error('Archive contains unsupported entries', { cause: error })\n  }\n  throw error\n}","preventionTips":["Produce archives only with the app's exporter.","Exclude OS metadata (__MACOSX, .DS_Store, Thumbs.db) when rezipping.","Keep importer and backup format versions aligned."],"tags":["backup","import","archive","unsupported","path","validation"],"backgroundTag":null,"analyzedSha":"81571269addb6bafb589a920b2883f1e1e084fd1","analyzedAt":"2026-08-12T21:51:44.981Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}