linshenkx/prompt-optimizer · error · Error
Invalid favorites JSON payload
Error message
Invalid favorites JSON payload
What it means
Thrown by parseFavoriteExportJson in packages/ui/src/utils/favorite-resource-package.ts when the favorites JSON string parses but is not an object containing an array-typed favorites field. This validates the payload consumed by exportData when re-packaging favorites, ensuring the favorites array exists before further processing. A raw JSON.parse SyntaxError is a separate failure that happens before this check.
Source
Thrown at packages/ui/src/utils/favorite-resource-package.ts:103
type ImportFavoriteResourcePackageOptions = {
favoriteManager: Pick<IFavoriteManager, 'importFavorites'>
imageStorageService?: Pick<IImageStorageService, 'getImage' | 'saveImage'> | null
mergeStrategy?: 'skip' | 'overwrite' | 'merge'
}
const FAVORITES_JSON_PATH = 'favorites.json'
const MANIFEST_JSON_PATH = 'manifest.json'
const IMAGE_RESOURCE_ROOT = 'resources/images/'
const isRecord = (value: unknown): value is Record<string, unknown> =>
!!value && typeof value === 'object' && !Array.isArray(value)
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 = (View on GitHub (pinned to 3e677b1d9f)
Solutions
- Log/inspect the JSON being passed: it must be an object like {"favorites": [...]}
- If the payload came from readFavoriteResourcePackage, re-export the favorites package from the source app
- Fix the producer to always serialize { favorites: FavoriteJson[] }
- Add a type guard (see defense) before calling exportData
Example fix
// before
await exportData({ favoritesJson: manifestJsonString }) // wrong file: throws Invalid favorites JSON payload
// after
const parsed = JSON.parse(favoritesJsonString)
if (!isRecord(parsed) || !Array.isArray(parsed.favorites)) {
throw new Error('Favorites file must be an object with a favorites array')
}
await exportData({ favoritesJson: favoritesJsonString }) Defensive patterns
Strategy: type-guard
Validate before calling
const isFavoriteExportJson = (v: unknown): v is { favorites: unknown[] } =>
typeof v === 'object' && v !== null && Array.isArray((v as { favorites?: unknown }).favorites)
// before calling exportData:
let parsed: unknown
try {
parsed = JSON.parse(favoritesJson)
} catch {
throw new Error('Favorites file is not valid JSON')
}
if (!isFavoriteExportJson(parsed)) {
throw new Error('Favorites file must contain a favorites array')
} Type guard
const isFavoriteExportJson = (v: unknown): v is FavoriteExportJson => typeof v === 'object' && v !== null && Array.isArray((v as FavoriteExportJson).favorites)
Try / catch
try {
await exportData({ favoritesJson })
} catch (e) {
if (e instanceof Error && e.message === 'Invalid favorites JSON payload') {
// wrong file or schema drift; re-export favorites from source
return
}
throw e
} Prevention
- Always pass the favorites.json payload, not manifest.json or app-data.json
- Validate the parsed shape with a type guard before exportData
- Pin the favorites schema version between producer and consumer
- Never hand-author favorites JSON without the top-level favorites array
When it happens
Trigger: Calling exportData with a favorites JSON string that is valid JSON but shaped wrong: a JSON array at the top level, an object whose favorites key is missing or is an object/string/number instead of an array, or an empty string edge case parsed into a non-record. It also fires when feed data from a different schema version is passed in.
Common situations: Schema drift after a favorites format change; passing the wrong JSON file (e.g. manifest.json or app-data.json instead of the favorites payload); hand-crafted import files; double-stringified JSON that parses to a string.
Related errors
- Invalid import data format
- variables[${index}] is missing a valid "position" object.
- variables[${index}].position is missing a valid "originalTex
- variables[${index}] is missing a valid "reason" field.
- Generation result is not a valid object.
AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27).
Data as JSON: /api/errors/eb75f8473faaa7cb.
Report an issue: GitHub.