chatboxai/chatbox · error

Duplicate session id in manifest

Error message

Duplicate session id in manifest: ${session.id}

What it means

Thrown by validateBackupManifestGraph while scanning manifest.sessions. Each session entry must carry a unique id; when a second session with an already-seen id is found, validation aborts. This protects the restore path, which keys session storage by id.

Solutions

  1. Inspect manifest.sessions and remove or rename the duplicate id entry.
  2. Re-export from the source so the exporter dedupes by id.
  3. When merging backups, dedupe sessions by id before packing the manifest.

Example fix

// before
validateBackupManifestGraph(manifest)

// after
const seen = new Set<string>()
manifest.sessions = manifest.sessions.filter((s) =>
  seen.has(s.id) ? false : (seen.add(s.id), true)
)
validateBackupManifestGraph(manifest)
Defensive patterns

Strategy: validation

Validate before calling

function findDuplicateSessionIds(manifest: BackupManifest): string[] {
  const seen = new Set<string>()
  const dups = new Set<string>()
  for (const s of manifest.sessions) (seen.has(s.id) ? dups : seen).add(s.id)
  return [...dups]
}

Try / catch

try {
  validateBackupManifestGraph(manifest)
} catch (error) {
  if (/Duplicate session id/.test((error as Error).message)) reportCorruptBackup(error)
  throw error
}

Prevention

When it happens

Trigger: Two entries in manifest.sessions share the same session.id. Produced by a hand-edited manifest, a merge of two exports, or an exporter that failed to dedupe by id.

Common situations: Merging two backup files; exporting a session list with a duplicated row; a sync collision that wrote the same session id twice.

Related errors


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

Appendix: source

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

  }),
  sessions: z.array(BackupSessionEntrySchema).max(50_000),
  resources: z.array(BackupResourceEntrySchema).max(50_000),
  warnings: z.array(BackupWarningSchema).max(50_000),
  stats: z.object({
    sessionCount: z.number().int().nonnegative(),
    resourceCount: z.number().int().nonnegative(),
    deduplicatedResourceCount: z.number().int().nonnegative(),
    warningCount: z.number().int().nonnegative(),
  }),
})
export type BackupManifest = z.infer<typeof BackupManifestSchema>

export function validateBackupManifestGraph(manifest: BackupManifest): void {
  const resourceIds = new Set<string>()
  const resourceKeys = new Set<string>()
  const sessionIds = new Set<string>()
  for (const session of manifest.sessions) {
    if (sessionIds.has(session.id)) throw new Error(`Duplicate session id in manifest: ${session.id}`)
    sessionIds.add(session.id)
    if (session.meta.id !== session.id) throw new Error(`Session metadata id does not match: ${session.id}`)
  }
  for (const resource of manifest.resources) {
    if (resourceIds.has(resource.id)) throw new Error(`Duplicate resource id in manifest: ${resource.id}`)
    resourceIds.add(resource.id)
    const ownResourceKeys = new Set<string>()
    for (const key of resource.originalStorageKeys) {
      if (ownResourceKeys.has(key)) throw new Error(`Resource contains a duplicate storage key: ${resource.id}`)
      ownResourceKeys.add(key)
      if (resourceKeys.has(key)) throw new Error(`Duplicate resource storage key in manifest: ${key}`)
      resourceKeys.add(key)
    }
    const ownSessionIds = new Set<string>()
    for (const sessionId of resource.sessionIds) {
      if (ownSessionIds.has(sessionId)) throw new Error(`Resource contains a duplicate session id: ${resource.id}`)
      ownSessionIds.add(sessionId)
      if (!sessionIds.has(sessionId)) throw new Error(`Resource references an unknown session: ${sessionId}`)

View on GitHub (pinned to 81571269ad)