chatboxai/chatbox · error · Error

Backup manifest entry list is incomplete

Error message

Backup manifest entry list is incomplete

What it means

Thrown as a final invariant in validateManifestEntries when the number of expected paths does not equal the number of staged entries. The preceding loops already reject duplicate descriptor paths (125), missing staged entries (126), and unexpected staged paths (128), so a size mismatch here indicates an internal logic error rather than bad archive data. Propagates after rollback.

Source

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

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

async function findAvailableCollisionKey(storage: BackupStorage, originalKey: string, reserved: Set<string>) {
  for (let attempt = 0; attempt < 100; attempt++) {
    let candidatePrefix = 'resource:imported'
    for (const prefix of ['picture:', 'file:', 'link:', 'parseFile-', 'parseUrl-']) {
      if (originalKey.startsWith(prefix)) {
        candidatePrefix = `${prefix}imported`
        break
      }
    }

View on GitHub (pinned to 81571269ad)

Solutions

  1. Treat as a code defect: audit validateManifestEntries and the descriptor list construction for missing/duplicate handling.
  2. Ensure stagedEntries and the manifest descriptors are not mutated concurrently during validation.
  3. Add a unit test with a known-good archive to confirm the invariant holds.
  4. Report with the full manifest if it reproduces.
Defensive patterns

Strategy: try-catch

Validate before calling

// No data-level pre-check applies; the invariant should be unreachable. In tests, assert it
// never fires for a corpus of well-formed archives.
for (const archive of validArchives) {
  const staged = await stage(archive)
  validateManifestEntries(parseManifest(archive), staged) // must not throw
}

Try / catch

try {
  await importBackupArchive(file, options)
} catch (error) {
  if (error instanceof Error && error.message === 'Backup manifest entry list is incomplete') {
    // Treat as a bug in validateManifestEntries or a concurrent-mutation issue.
    throw new Error('Internal invariant violated; report this archive', { cause: error })
  }
  throw error
}

Prevention

When it happens

Trigger: expectedPaths.size !== stagedEntries.size after the duplicate/missing/unexpected checks all passed - only reachable through a bug in descriptor construction or set bookkeeping.

Common situations: Essentially unreachable with a well-formed archive; indicates a regression in validateManifestEntries, a manifest schema that permits duplicate-but-distinct descriptors, or concurrent mutation of stagedEntries during validation.

Related errors


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