chatboxai/chatbox · error · Error

Backup entry is missing: ${descriptor.path}

Error message

Backup entry is missing: ${descriptor.path}

What it means

Thrown when a manifest descriptor references an archive path that has no matching staged entry - the zip did not contain that file. The manifest is the source of truth; every listed entry must physically exist in the archive. Propagates after rollback.

Source

Thrown at src/renderer/packages/backup/import-backup.ts:93

function parseJson(bytes: Uint8Array, path: string): unknown {
  if (bytes.length > MAX_BACKUP_JSON_ENTRY_BYTES) throw new Error(`Backup JSON entry is too large: ${path}`)
  return JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes)) as unknown
}

function validateManifestEntries(manifest: BackupManifest, stagedEntries: Map<string, StagedEntry>) {
  const descriptors = [
    manifest.data.settings,
    manifest.data.copilots,
    manifest.data.sessionSettings,
    ...manifest.sessions,
    ...manifest.resources,
  ].filter((entry): entry is NonNullable<typeof entry> => Boolean(entry))
  const expectedPaths = new Set<string>([BACKUP_MANIFEST_PATH])
  for (const descriptor of descriptors) {
    if (expectedPaths.has(descriptor.path)) throw new Error(`Manifest contains a duplicate path: ${descriptor.path}`)
    expectedPaths.add(descriptor.path)
    const staged = stagedEntries.get(descriptor.path)
    if (!staged) throw new Error(`Backup entry is missing: ${descriptor.path}`)
    if (staged.size !== descriptor.size) throw new Error(`Backup entry size mismatch: ${descriptor.path}`)
    if (staged.checksum.value !== descriptor.checksum.value) {
      throw new Error(`Backup entry checksum mismatch: ${descriptor.path}`)
    }
  }
  for (const path of stagedEntries.keys()) {
    if (!expectedPaths.has(path)) throw new Error(`Backup contains an entry not listed in manifest: ${path}`)
  }
  if (expectedPaths.size !== stagedEntries.size) throw new Error('Backup manifest entry list is incomplete')
  validateBackupManifestGraph(manifest)
}

async function readStagedResource(storage: BackupStorage, plan: Pick<ResourceWritePlan, 'resource' | 'tempKey'>) {
  const base64 = await storage.getBlob(plan.tempKey)
  if (base64 === null) throw new Error(`Staged resource is missing: ${plan.resource.path}`)
  return decodeStoredBlob(base64ToBytes(base64), plan.resource.encoding, plan.resource.mimeType)
}

View on GitHub (pinned to 81571269ad)

Solutions

  1. Re-download or re-create the backup file from its source.
  2. Verify archive integrity (unzip listing) before import.
  3. If the source is unrecoverable and you accept data loss, edit the manifest to remove the dangling descriptor.

Example fix

// before: archive missing files the manifest references
await importBackupArchive(file, options)
// after: confirm every manifest path is present in the zip first
const present = new Set(zipEntryPaths)
const missing = descriptors.map((d) => d.path).filter((p) => !present.has(p))
if (missing.length) throw new Error('Archive is missing: ' + missing.join(', '))
Defensive patterns

Strategy: validation

Validate before calling

// Confirm every manifest descriptor path is present in the archive listing.
const listing = await listZipEntries(file)
const present = new Set(listing)
const required = descriptors.map((d) => d.path)
const absent = required.filter((p) => !present.has(p))
if (absent.length) throw new Error('Archive is incomplete; missing: ' + absent.join(', '))

Try / catch

try {
  await importBackupArchive(file, options)
} catch (error) {
  if (error instanceof Error && error.message.startsWith('Backup entry is missing')) {
    // Re-download or re-create the backup file.
    throw new Error('Backup file is incomplete', { cause: error })
  }
  throw error
}

Prevention

When it happens

Trigger: manifest.sessions, manifest.resources, or manifest.data.* lists a path, but stagedEntries has no entry for it because the zip stream lacked that file.

Common situations: Interrupted download/copy of the .backup file; a file removed from the zip after creation; a manifest and zip taken from mismatched export runs.

Related errors


AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12). Data as JSON: /api/errors/68e5200b8eef02de. Report an issue: GitHub.