{"record":{"id":"581287243401c21c","repo":"linshenkx/prompt-optimizer","slug":"favorites-package-is-missing-manifest-json","errorCode":null,"errorMessage":"favorites package is missing manifest.json","messagePattern":"favorites package is missing manifest\\.json","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ui/src/utils/favorite-resource-package.ts","lineNumber":226,"sourceCode":"    manifest,\n    missingResourceIds,\n  }\n}\n\nexport const readFavoriteResourcePackage = (\n  input: ArrayBuffer | Uint8Array,\n): {\n  manifest: FavoriteResourcePackageManifest\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_PATH]\n  const favoritesBytes = files[FAVORITES_JSON_PATH]\n\n  if (!manifestBytes) {\n    throw new Error('favorites package is missing manifest.json')\n  }\n  if (!favoritesBytes) {\n    throw new Error('favorites package is missing favorites.json')\n  }\n\n  return {\n    manifest: parseManifest(strFromU8(manifestBytes)),\n    favoritesJson: strFromU8(favoritesBytes),\n    files,\n  }\n}\n\nconst restoreFavoritePackageResources = async (\n  manifest: FavoriteResourcePackageManifest,\n  files: Record<string, Uint8Array>,\n  imageStorageService: ImportFavoriteResourcePackageOptions['imageStorageService'],\n): Promise<FavoriteResourceRestoreReport> => {\n  const report: FavoriteResourceRestoreReport = {","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/ui/src/utils/favorite-resource-package.ts#L208-L244","documentation":"Thrown by readFavoriteResourcePackage in packages/ui/src/utils/favorite-resource-package.ts after unzipSync when the zip has no entry at MANIFEST_JSON_PATH ('manifest.json'). The manifest is mandatory in the favorites package format, so any archive lacking it is rejected before content parsing. A non-zip input would fail inside unzipSync first, so this means a valid zip without the entry.","triggerScenarios":"Passing a zip without a root-level 'manifest.json': wrong file uploaded, manifest nested under a directory, differently-cased entry name, or an archive built by external tooling that doesn't follow the package layout.","commonSituations":"Users selecting an unrelated zip in the import dialog; re-zipped packages with folder prefixes; zips created on case-sensitive systems with different casing; transferring packages through tools that rewrite entry names.","solutions":["Verify the uploaded file is a favorites package exported by the app","List zip entries and confirm 'manifest.json' is at the archive root with exact casing","Re-zip with manifest.json at top level, or regenerate via the app's exporter","Pre-validate entries before calling readFavoriteResourcePackage for a better UX"],"exampleFix":"// before\nconst pkg = readFavoriteResourcePackage(bytes) // throws: missing manifest.json\n\n// after\nconst entries = Object.keys(unzipSync(bytes))\nif (!entries.includes('manifest.json')) {\n  throw new Error(`Invalid favorites package; entries: ${entries.join(', ')}`)\n}\nconst pkg = readFavoriteResourcePackage(bytes)","handlingStrategy":"validation","validationCode":"import { unzipSync } from 'fflate'\n\nconst looksLikeFavoritesPackage = (bytes: Uint8Array): boolean => {\n  try {\n    return 'manifest.json' in unzipSync(bytes)\n  } catch {\n    return false\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  const pkg = readFavoriteResourcePackage(bytes)\n} catch (e) {\n  if (e instanceof Error && e.message.includes('missing manifest.json')) {\n    showFileError('Not a favorites package')\n    return\n  }\n  throw e\n}","preventionTips":["Restrict imports to files produced by the app's favorites export","Verify zip entries before parsing","Ensure manifest.json stays at the archive root when repackaging","Use exact lowercase entry names when building packages programmatically"],"tags":["zip","missing-file","manifest","favorites"],"backgroundTag":"zip-missing-entry","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}