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
- Recompute stats from the arrays right before packing the manifest.
- Set sessionCount = sessions.length, resourceCount = resources.length, warningCount = warnings.length.
- 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
- Compute stats last, after all entry arrays are finalized.
- Derive counts from array length, never from a running counter.
- Remember deduplicatedResourceCount is not checked by this guard.
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
- Manifest contains a duplicate path: ${descriptor.path}
- Session id does not match manifest: ${descriptor.path}
- Duplicate session id in manifest: ${session.id}
- Session metadata id does not match: ${session.id}
- Duplicate resource id in manifest: ${resource.id}
AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12).
Data as JSON: /api/errors/fd1a51372f50d9de.
Report an issue: GitHub.