{"record":{"id":"ca566e95ed9baeae","repo":"linshenkx/prompt-optimizer","slug":"app-backup-package-is-missing-favorites-json","errorCode":null,"errorMessage":"app backup package is missing favorites.json","messagePattern":"app backup package is missing favorites\\.json","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ui/src/utils/data-manager-resource-package.ts","lineNumber":296,"sourceCode":"  manifest: DataManagerResourcePackageManifest\n  appDataJson: string\n  favoritesJson: string\n  files: Record<string, Uint8Array>\n} => {\n  const bytes = input instanceof Uint8Array ? input : new Uint8Array(input)\n  const files = unzipSync(bytes)\n  const manifestBytes = files['manifest.json']\n  const appDataBytes = files[APP_DATA_JSON_PATH]\n  const favoritesBytes = files[FAVORITES_JSON_PATH]\n\n  if (!manifestBytes) {\n    throw new Error('app backup package is missing manifest.json')\n  }\n  if (!appDataBytes) {\n    throw new Error('app backup package is missing app-data.json')\n  }\n  if (!favoritesBytes) {\n    throw new Error('app backup package is missing favorites.json')\n  }\n\n  return {\n    manifest: parseManifest(strFromU8(manifestBytes)),\n    appDataJson: strFromU8(appDataBytes),\n    favoritesJson: strFromU8(favoritesBytes),\n    files,\n  }\n}\n\nconst getImportStorageService = (\n  store: DataManagerImageStoreKey,\n  options: ImportDataManagerResourcePackageOptions,\n): Pick<IImageStorageService, 'getImage' | 'saveImage'> | null | undefined =>\n  store === 'favoriteImages'\n    ? options.favoriteImageStorageService\n    : options.imageStorageService\n","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/ui/src/utils/data-manager-resource-package.ts#L278-L314","documentation":"Thrown by readDataManagerResourcePackage in packages/ui/src/utils/data-manager-resource-package.ts when the zip contains manifest.json and app-data.json but no entry at FAVORITES_JSON_PATH ('favorites.json'). Favorites are a required part of the app backup format, so the reader aborts. It is the last of the three entry-presence checks before parseManifest runs.","triggerScenarios":"A zip with manifest.json and app-data.json but no favorites.json entry — e.g. a package built by an older exporter that didn't include favorites, an archive where favorites.json was renamed/removed, or a partial export that finished app-data but not favorites.","commonSituations":"Version skew between an exporter that omitted favorites and the current reader that requires it; users deleting 'unneeded' files from the archive; re-zip tooling that skips files; truncated downloads.","solutions":["Confirm favorites.json exists at the zip root; if missing, re-export the backup with the current app version","If you control the exporter, ensure it always writes favorites.json (even an empty favorites array) into the package","Pre-check required entries before calling readDataManagerResourcePackage","For legacy packages without favorites, write a small migration that injects an empty favorites.json before reading"],"exampleFix":"// before\nconst pkg = readDataManagerResourcePackage(bytes) // throws: missing favorites.json\n\n// after (legacy package migration)\nconst files = unzipSync(bytes)\nif (!files['favorites.json']) {\n  files['favorites.json'] = strToU8(JSON.stringify({ favorites: [] }))\n  bytes = zipSync(files)\n}\nconst pkg = readDataManagerResourcePackage(bytes)","handlingStrategy":"validation","validationCode":"import { unzipSync } from 'fflate'\n\nconst isCompleteAppBackup = (bytes: Uint8Array): boolean => {\n  try {\n    const entries = Object.keys(unzipSync(bytes))\n    return ['manifest.json', 'app-data.json', 'favorites.json'].every((n) => entries.includes(n))\n  } catch {\n    return false\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  const pkg = readDataManagerResourcePackage(bytes)\n} catch (e) {\n  if (e instanceof Error && e.message.includes('missing favorites.json')) {\n    // legacy/partial package: re-export or inject empty favorites\n    return\n  }\n  throw e\n}","preventionTips":["Always include favorites.json in exports, even when empty","Check zip entry lists when repackaging backups","Pre-validate required entries before calling the reader","Support legacy packages via a migration that injects an empty favorites payload"],"tags":["zip","missing-file","backup-restore","favorites"],"backgroundTag":"zip-missing-entry","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}