{"record":{"id":"5a8a30b9bdda4777","repo":"linshenkx/prompt-optimizer","slug":"app-backup-package-is-missing-manifest-json","errorCode":null,"errorMessage":"app backup package is missing manifest.json","messagePattern":"app backup package is missing manifest\\.json","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ui/src/utils/data-manager-resource-package.ts","lineNumber":290,"sourceCode":"  }\n}\n\nexport const readDataManagerResourcePackage = (\n  input: ArrayBuffer | Uint8Array,\n): {\n  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,","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/ui/src/utils/data-manager-resource-package.ts#L272-L308","documentation":"Thrown by readDataManagerResourcePackage in packages/ui/src/utils/data-manager-resource-package.ts after unzipSync when the zip archive contains no entry named 'manifest.json'. The reader treats manifest.json as the mandatory index of an app backup package, so an archive without it is rejected immediately. This fires before any content parsing occurs.","triggerScenarios":"Passing a Uint8Array/ArrayBuffer zip that lacks a top-level 'manifest.json' entry: e.g. a random zip file, a zip whose manifest sits in a subdirectory (e.g. backup/manifest.json), or a zip built with a different entry name or casing (Manifest.json). Note unzipSync on non-zip bytes would throw its own error first, so this specifically means a valid zip without that entry.","commonSituations":"User picks the wrong file in a restore file-picker; a repackaged/re-zipped backup lost the top-level manifest; tooling that re-zips with folder prefixes; case-sensitive filesystems or zip tools that rename entries.","solutions":["Confirm you selected the actual exported .app backup package, not an arbitrary zip","List the zip entries and verify 'manifest.json' exists at the archive root (no directory prefix, exact lowercase name)","If the manifest is nested, re-zip the contents so manifest.json is at the top level, or extract-and-repackage via the app's exporter","Validate the file before calling the API (see validation code) so users get a friendly message"],"exampleFix":"// before\nconst pkg = readDataManagerResourcePackage(bytes) // throws: missing manifest.json\n\n// after\nconst entries = Object.keys(unzipSync(bytes))\nif (!entries.includes('manifest.json')) {\n  throw new Error(`Not an app backup package; expected manifest.json, found: ${entries.join(', ')}`)\n}\nconst pkg = readDataManagerResourcePackage(bytes)","handlingStrategy":"validation","validationCode":"import { unzipSync } from 'fflate'\n\nconst looksLikeAppBackup = (bytes: Uint8Array): boolean => {\n  try {\n    return 'manifest.json' in unzipSync(bytes)\n  } catch {\n    return false // not a zip at all\n  }\n}\n\nif (!looksLikeAppBackup(bytes)) {\n  // reject file in the picker before calling readDataManagerResourcePackage\n}","typeGuard":null,"tryCatchPattern":"try {\n  const pkg = readDataManagerResourcePackage(bytes)\n} catch (e) {\n  if (e instanceof Error && e.message.includes('missing manifest.json')) {\n    showFileError('Selected file is not an app backup package')\n    return\n  }\n  throw e\n}","preventionTips":["Accept only .zip/.backup files produced by the app's export in the file picker","Validate zip entries before invoking the reader","Restrict file-picker extensions and show the expected format in the UI","Log the zip's entry list on failure to speed up diagnosis"],"tags":["zip","missing-file","backup-restore","manifest"],"backgroundTag":"zip-missing-entry","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}