{"record":{"id":"3ea6c354621ef1bb","repo":"linshenkx/prompt-optimizer","slug":"invalid-favorites-package-manifest","errorCode":null,"errorMessage":"Invalid favorites package manifest","messagePattern":"Invalid favorites package manifest","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ui/src/utils/favorite-resource-package.ts","lineNumber":116,"sourceCode":"const textToZipBytes = (text: string): Uint8Array => copyBytes(strToU8(text))\n\nconst parseFavoriteExportJson = (json: string): FavoriteExportJson => {\n  const parsed = JSON.parse(json) as unknown\n  if (!isRecord(parsed) || !Array.isArray(parsed.favorites)) {\n    throw new Error('Invalid favorites JSON payload')\n  }\n  return parsed as FavoriteExportJson\n}\n\nconst parseManifest = (json: string): FavoriteResourcePackageManifest => {\n  const parsed = JSON.parse(json) as unknown\n  if (\n    !isRecord(parsed) ||\n    parsed.schemaVersion !== FAVORITE_RESOURCE_PACKAGE_SCHEMA_VERSION ||\n    !Array.isArray(parsed.resources) ||\n    !Array.isArray(parsed.missingResourceIds)\n  ) {\n    throw new Error('Invalid favorites package manifest')\n  }\n  return parsed as FavoriteResourcePackageManifest\n}\n\nconst getExportStorageCandidates = (\n  options: Pick<ExportFavoriteResourcePackageOptions, 'imageStorageService' | 'imageStorageServices'>,\n): Array<Pick<IImageStorageService, 'getImage'>> => {\n  const candidates = options.imageStorageServices?.length\n    ? options.imageStorageServices\n    : [options.imageStorageService]\n\n  return candidates.filter((service): service is Pick<IImageStorageService, 'getImage'> => !!service)\n}\n\nconst getImageFromCandidates = async (\n  candidates: Array<Pick<IImageStorageService, 'getImage'>>,\n  assetId: string,\n): Promise<FullImageData | null> => {","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/ui/src/utils/favorite-resource-package.ts#L98-L134","documentation":"Thrown by parseManifest (called from readFavoriteResourcePackage in packages/ui/src/utils/favorite-resource-package.ts) when the favorites package's manifest.json parses but fails validation: it must be a record whose schemaVersion equals FAVORITE_RESOURCE_PACKAGE_SCHEMA_VERSION and whose resources and missingResourceIds are arrays. It distinguishes a structurally invalid manifest from a merely unparseable one (which would throw a SyntaxError from JSON.parse first).","triggerScenarios":"Calling readFavoriteResourcePackage on a zip whose manifest.json has a different schemaVersion (package from another app version), missing or non-array resources / missingResourceIds fields, or a top-level non-object (array/string/number). Commonly seen after format migrations.","commonSituations":"Restoring a favorites package exported by an older/newer release; hand-editing the manifest; feeding an app backup package manifest (different schema) into the favorites reader; truncated manifests that still parse as JSON scalars.","solutions":["Check manifest.json inside the package: confirm schemaVersion matches FAVORITE_RESOURCE_PACKAGE_SCHEMA_VERSION and resources/missingResourceIds are arrays","Re-export the favorites package with the current app version","Ensure you're passing a favorites package, not an app backup package (they have different manifests)","If cross-version support is needed, write a manifest migration step before validation"],"exampleFix":"// before\nconst pkg = readFavoriteResourcePackage(bytes) // throws: Invalid favorites package manifest\n\n// after\nconst m = JSON.parse(strFromU8(unzipSync(bytes)['manifest.json']))\nif (m?.schemaVersion !== FAVORITE_RESOURCE_PACKAGE_SCHEMA_VERSION) {\n  throw new Error(`Unsupported favorites package schema: ${m?.schemaVersion}`)\n}\nconst pkg = readFavoriteResourcePackage(bytes)","handlingStrategy":"validation","validationCode":"import { unzipSync, strFromU8 } from 'fflate'\n\nconst hasValidFavoriteManifest = (bytes: Uint8Array): boolean => {\n  try {\n    const m = JSON.parse(strFromU8(unzipSync(bytes)['manifest.json']))\n    return (\n      typeof m === 'object' && m !== null &&\n      m.schemaVersion === FAVORITE_RESOURCE_PACKAGE_SCHEMA_VERSION &&\n      Array.isArray(m.resources) &&\n      Array.isArray(m.missingResourceIds)\n    )\n  } catch {\n    return false\n  }\n}","typeGuard":"const isFavoriteManifest = (v: unknown): v is FavoriteResourcePackageManifest =>\n  typeof v === 'object' && v !== null &&\n  (v as FavoriteResourcePackageManifest).schemaVersion === FAVORITE_RESOURCE_PACKAGE_SCHEMA_VERSION &&\n  Array.isArray((v as FavoriteResourcePackageManifest).resources) &&\n  Array.isArray((v as FavoriteResourcePackageManifest).missingResourceIds)","tryCatchPattern":"try {\n  const pkg = readFavoriteResourcePackage(bytes)\n} catch (e) {\n  if (e instanceof Error && e.message === 'Invalid favorites package manifest') {\n    // incompatible package version; request a fresh export\n    return\n  }\n  throw e\n}","preventionTips":["Only import favorites packages exported by a compatible app version","Don't mix app backup manifests with favorites packages","Bump FAVORITE_RESOURCE_PACKAGE_SCHEMA_VERSION with format changes and migrate manifests","Pre-validate schemaVersion for a clear version-mismatch error"],"tags":["zip","manifest","schema-validation","favorites"],"backgroundTag":"package-manifest-validation-failed","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}