linshenkx/prompt-optimizer · error · Error

Invalid favorites package manifest

Error message

Invalid favorites package manifest

What it means

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).

Source

Thrown at packages/ui/src/utils/favorite-resource-package.ts:116

const textToZipBytes = (text: string): Uint8Array => copyBytes(strToU8(text))

const parseFavoriteExportJson = (json: string): FavoriteExportJson => {
  const parsed = JSON.parse(json) as unknown
  if (!isRecord(parsed) || !Array.isArray(parsed.favorites)) {
    throw new Error('Invalid favorites JSON payload')
  }
  return parsed as FavoriteExportJson
}

const parseManifest = (json: string): FavoriteResourcePackageManifest => {
  const parsed = JSON.parse(json) as unknown
  if (
    !isRecord(parsed) ||
    parsed.schemaVersion !== FAVORITE_RESOURCE_PACKAGE_SCHEMA_VERSION ||
    !Array.isArray(parsed.resources) ||
    !Array.isArray(parsed.missingResourceIds)
  ) {
    throw new Error('Invalid favorites package manifest')
  }
  return parsed as FavoriteResourcePackageManifest
}

const getExportStorageCandidates = (
  options: Pick<ExportFavoriteResourcePackageOptions, 'imageStorageService' | 'imageStorageServices'>,
): Array<Pick<IImageStorageService, 'getImage'>> => {
  const candidates = options.imageStorageServices?.length
    ? options.imageStorageServices
    : [options.imageStorageService]

  return candidates.filter((service): service is Pick<IImageStorageService, 'getImage'> => !!service)
}

const getImageFromCandidates = async (
  candidates: Array<Pick<IImageStorageService, 'getImage'>>,
  assetId: string,
): Promise<FullImageData | null> => {

View on GitHub (pinned to 3e677b1d9f)

Solutions

  1. Check manifest.json inside the package: confirm schemaVersion matches FAVORITE_RESOURCE_PACKAGE_SCHEMA_VERSION and resources/missingResourceIds are arrays
  2. Re-export the favorites package with the current app version
  3. Ensure you're passing a favorites package, not an app backup package (they have different manifests)
  4. If cross-version support is needed, write a manifest migration step before validation

Example fix

// before
const pkg = readFavoriteResourcePackage(bytes) // throws: Invalid favorites package manifest

// after
const m = JSON.parse(strFromU8(unzipSync(bytes)['manifest.json']))
if (m?.schemaVersion !== FAVORITE_RESOURCE_PACKAGE_SCHEMA_VERSION) {
  throw new Error(`Unsupported favorites package schema: ${m?.schemaVersion}`)
}
const pkg = readFavoriteResourcePackage(bytes)
Defensive patterns

Strategy: validation

Validate before calling

import { unzipSync, strFromU8 } from 'fflate'

const hasValidFavoriteManifest = (bytes: Uint8Array): boolean => {
  try {
    const m = JSON.parse(strFromU8(unzipSync(bytes)['manifest.json']))
    return (
      typeof m === 'object' && m !== null &&
      m.schemaVersion === FAVORITE_RESOURCE_PACKAGE_SCHEMA_VERSION &&
      Array.isArray(m.resources) &&
      Array.isArray(m.missingResourceIds)
    )
  } catch {
    return false
  }
}

Type guard

const isFavoriteManifest = (v: unknown): v is FavoriteResourcePackageManifest =>
  typeof v === 'object' && v !== null &&
  (v as FavoriteResourcePackageManifest).schemaVersion === FAVORITE_RESOURCE_PACKAGE_SCHEMA_VERSION &&
  Array.isArray((v as FavoriteResourcePackageManifest).resources) &&
  Array.isArray((v as FavoriteResourcePackageManifest).missingResourceIds)

Try / catch

try {
  const pkg = readFavoriteResourcePackage(bytes)
} catch (e) {
  if (e instanceof Error && e.message === 'Invalid favorites package manifest') {
    // incompatible package version; request a fresh export
    return
  }
  throw e
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27). Data as JSON: /api/errors/3ea6c354621ef1bb. Report an issue: GitHub.