linshenkx/prompt-optimizer · error · Error
Invalid app backup package manifest
Error message
Invalid app backup package manifest
What it means
Thrown by parseManifest (called from readDataManagerResourcePackage in packages/ui/src/utils/data-manager-resource-package.ts) when the unzipped backup's manifest.json fails structural validation: schemaVersion must equal DATA_MANAGER_RESOURCE_PACKAGE_SCHEMA_VERSION, appDataPath must equal APP_DATA_JSON_PATH, favoritesPath must equal FAVORITES_JSON_PATH, and resources/missingResources must be arrays. It means the zip is not a valid app backup package produced by this code's exporter. It protects the restore path from partially written or foreign archives.
Source
Thrown at packages/ui/src/utils/data-manager-resource-package.ts:160
]
}
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 parseManifest = (json: string): DataManagerResourcePackageManifest => {
const parsed = JSON.parse(json) as unknown
if (
!isRecord(parsed) ||
parsed.schemaVersion !== DATA_MANAGER_RESOURCE_PACKAGE_SCHEMA_VERSION ||
parsed.appDataPath !== APP_DATA_JSON_PATH ||
parsed.favoritesPath !== FAVORITES_JSON_PATH ||
!Array.isArray(parsed.resources) ||
!Array.isArray(parsed.missingResources)
) {
throw new Error('Invalid app backup package manifest')
}
return parsed as DataManagerResourcePackageManifest
}
const collectStoreResources = async (
config: ImageStoreExportConfig,
files: Record<string, Uint8Array>,
): Promise<{
resources: DataManagerResourceManifestEntry[]
missing: Array<{ store: DataManagerImageStoreKey; id: string }>
}> => {
if (!config.service) {
return { resources: [], missing: [] }
}
const metadataList = await config.service.listAllMetadata()
const resources: DataManagerResourceManifestEntry[] = []
const missing: Array<{ store: DataManagerImageStoreKey; id: string }> = []View on GitHub (pinned to 3e677b1d9f)
Solutions
- Verify the package was exported by the same app version (or a version sharing the same DATA_MANAGER_RESOURCE_PACKAGE_SCHEMA_VERSION); re-export the backup from the source app
- Unzip the archive and inspect manifest.json: confirm schemaVersion, appDataPath and favoritesPath values and that resources/missingResources are arrays
- If you maintain the exporter, regenerate the package rather than hand-editing the manifest
- If supporting cross-version restores, add a migration step that upgrades older manifests to the current schemaVersion before validation
Example fix
// before
const pkg = readDataManagerResourcePackage(bytes) // throws: Invalid app backup package manifest
// after
const manifest = JSON.parse(strFromU8(unzipSync(bytes)['manifest.json']))
if (manifest.schemaVersion !== DATA_MANAGER_RESOURCE_PACKAGE_SCHEMA_VERSION) {
throw new Error(`Unsupported backup schema version: ${manifest.schemaVersion}`)
}
const pkg = readDataManagerResourcePackage(bytes) Defensive patterns
Strategy: validation
Validate before calling
import { unzipSync } from 'fflate'
import { strFromU8 } from 'fflate'
const isValidAppBackupManifest = (json: string): boolean => {
try {
const m = JSON.parse(json)
return (
typeof m === 'object' && m !== null &&
m.schemaVersion === DATA_MANAGER_RESOURCE_PACKAGE_SCHEMA_VERSION &&
m.appDataPath === 'app-data.json' &&
m.favoritesPath === 'favorites.json' &&
Array.isArray(m.resources) &&
Array.isArray(m.missingResources)
)
} catch {
return false
}
}
// before readDataManagerResourcePackage:
const files = unzipSync(bytes)
const ok = !!files['manifest.json'] && isValidAppBackupManifest(strFromU8(files['manifest.json'])) Type guard
const isAppBackupManifest = (v: unknown): v is DataManagerResourcePackageManifest => typeof v === 'object' && v !== null && (v as DataManagerResourcePackageManifest).schemaVersion === DATA_MANAGER_RESOURCE_PACKAGE_SCHEMA_VERSION && Array.isArray((v as DataManagerResourcePackageManifest).resources) && Array.isArray((v as DataManagerResourcePackageManifest).missingResources)
Try / catch
try {
const pkg = readDataManagerResourcePackage(bytes)
} catch (e) {
if (e instanceof Error && e.message === 'Invalid app backup package manifest') {
// show 'incompatible or corrupted backup' UI; do not retry
return
}
throw e
} Prevention
- Only feed packages exported by the same app version into readDataManagerResourcePackage
- Validate the manifest's schemaVersion before restore and surface a version-mismatch message
- Never hand-edit manifest fields inside exported packages
- Keep a migration layer when bumping DATA_MANAGER_RESOURCE_PACKAGE_SCHEMA_VERSION
When it happens
Trigger: Calling readDataManagerResourcePackage on a zip whose manifest.json has a mismatched schemaVersion (package written by an older/newer app version), wrong appDataPath/favoritesPath values, or missing/non-array resources or missingResources fields. Also triggered by a hand-edited or truncated manifest.json, or JSON.parse succeeding but yielding a non-record (e.g. an array or string).
Common situations: Restoring a backup created by a different app version after a schema migration; renaming the internal app-data.json/favorites.json files inside the zip; passing a generic zip that happens to contain a manifest.json; corrupting the manifest during download/transfer. Note JSON.parse failures throw a SyntaxError before this check, so this error specifically means parseable-but-invalid content.
Related errors
- app backup package is missing manifest.json
- Invalid favorites package manifest
- app backup package is missing app-data.json
- app backup package is missing favorites.json
- favorites package is missing manifest.json
AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27).
Data as JSON: /api/errors/9e04e2746bcfb7d1.
Report an issue: GitHub.