chatboxai/chatbox · error

Backup manifest statistics do not match its entries

Error message

Backup manifest statistics do not match its entries

What it means

Thrown when the manifest's declared stats counts disagree with the actual array lengths: sessionCount must equal sessions.length, resourceCount must equal resources.length, and warningCount must equal warnings.length. Note that deduplicatedResourceCount is intentionally NOT checked here.

Source

Thrown at src/renderer/packages/backup/types.ts:151

      if (!resourcesById.get(resourceId)?.sessionIds.includes(session.id)) {
        throw new Error(`Session/resource mapping is inconsistent: ${session.id}/${resourceId}`)
      }
    }
  }
  for (const resource of manifest.resources) {
    for (const sessionId of resource.sessionIds) {
      const session = sessionsById.get(sessionId)
      if (!session?.resourceIds.includes(resource.id)) {
        throw new Error(`Resource/session mapping is inconsistent: ${resource.id}/${sessionId}`)
      }
    }
  }
  if (
    manifest.stats.sessionCount !== manifest.sessions.length ||
    manifest.stats.resourceCount !== manifest.resources.length ||
    manifest.stats.warningCount !== manifest.warnings.length
  ) {
    throw new Error('Backup manifest statistics do not match its entries')
  }
}

export interface BackupProgress {
  phase: 'preparing' | 'sessions' | 'resources' | 'packing' | 'reading' | 'validating' | 'restoring'
  current: number
  total: number
  label?: string
}

export interface BackupStorage {
  getAllKeys(): Promise<string[]>
  getItem<T>(key: string, initialValue: T): Promise<T>
  setItemNow<T>(key: string, value: T): Promise<void>
  removeItem(key: string): Promise<void>
  getBlob(key: string): Promise<string | null>
  setBlob(key: string, value: string): Promise<void>
  delBlob(key: string): Promise<void>

View on GitHub (pinned to 81571269ad)

Solutions

  1. Recompute stats from the arrays right before packing the manifest.
  2. Set sessionCount = sessions.length, resourceCount = resources.length, warningCount = warnings.length.
  3. Re-export.

Example fix

// before
validateBackupManifestGraph(manifest)

// after
manifest.stats = {
  ...manifest.stats,
  sessionCount: manifest.sessions.length,
  resourceCount: manifest.resources.length,
  warningCount: manifest.warnings.length,
}
Defensive patterns

Strategy: validation

Validate before calling

function statsMatchEntries(manifest: BackupManifest): boolean {
  return (
    manifest.stats.sessionCount === manifest.sessions.length &&
    manifest.stats.resourceCount === manifest.resources.length &&
    manifest.stats.warningCount === manifest.warnings.length
  )
}

Try / catch

try {
  validateBackupManifestGraph(manifest)
} catch (error) {
  if (/statistics do not match/.test((error as Error).message)) recomputeStats(manifest)
  throw error
}

Prevention

When it happens

Trigger: manifest.stats.sessionCount / resourceCount / warningCount differs from the corresponding array length.

Common situations: Stats computed before entries were finalized; a hand-edit that added/removed an entry without updating stats; an exporter off-by-one.

Related errors


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