chatboxai/chatbox · error · Error

Backup JSON entry is too large: ${path}

Error message

Backup JSON entry is too large: ${path}

What it means

Thrown by parseJson during the import reading phase when an entry's decoded UTF-8 bytes exceed MAX_BACKUP_JSON_ENTRY_BYTES (128 MiB). It guards JSON.parse against pathological inputs. readZipFileEntries already caps each entry via backupEntryByteLimit, so this is a secondary defense; if reached, the import aborts, rollback runs (commitStarted is false, so only temps are cleaned), and the error propagates.

Source

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

    session: Session
  ) => Promise<{ session: Session; warnings: BackupWarning[]; rollback?: () => Promise<void> }>
}

export interface BackupImportResult {
  manifest: BackupManifest
  warnings: BackupWarning[]
  restoredSessionCount: number
  restoredResourceCount: number
}

function throwIfAborted(signal?: AbortSignal) {
  if (signal?.aborted) {
    throw signal.reason instanceof Error ? signal.reason : new DOMException('Operation canceled', 'AbortError')
  }
}

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

View on GitHub (pinned to 81571269ad)

Solutions

  1. Reduce the offending JSON entry below 128 MiB (split the session, trim message history) and re-export.
  2. Reject the file before import by pre-scanning entry.uncompressedSize.
  3. Raise MAX_BACKUP_JSON_ENTRY_BYTES only after verifying the memory budget for JSON.parse.
  4. Regenerate the backup from a current app version.

Example fix

// before: import blows up parsing a 200 MiB session.json
await importBackupArchive(file, options)
// after: pre-scan and reject oversized entries
await readZipFileEntries(file, async (entry) => {
  if (isBackupJsonPath(entry.path) && entry.uncompressedSize > MAX_BACKUP_JSON_ENTRY_BYTES) {
    throw new Error('Refusing oversized entry ' + entry.path)
  }
})
await importBackupArchive(file, options)
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-scan the zip's JSON entries and reject any over the JSON cap before importing.
import { MAX_BACKUP_JSON_ENTRY_BYTES } from './types'
import { isBackupJsonPath } from './archive-layout'
await readZipFileEntries(file, async (entry) => {
  if (isBackupJsonPath(entry.path) && entry.uncompressedSize > MAX_BACKUP_JSON_ENTRY_BYTES) {
    throw new Error('Entry too large to import: ' + entry.path)
  }
})

Type guard

// True when a JSON entry's uncompressed size fits the JSON budget.
const jsonEntryFits = (uncompressedSize: number): boolean =>
  uncompressedSize <= MAX_BACKUP_JSON_ENTRY_BYTES

Try / catch

try {
  await importBackupArchive(file, options)
} catch (error) {
  if (error instanceof Error && error.message.startsWith('Backup JSON entry is too large')) {
    // The offending path is embedded in the message; trim the source and re-export.
    throw new Error('Cannot import: a JSON entry exceeds 128 MiB', { cause: error })
  }
  throw error
}

Prevention

When it happens

Trigger: A JSON archive entry (manifest.json, settings.json, copilots.json, session-settings.json, or a sessions/<id>/session.json) is larger than 128 MiB uncompressed and reached parseJson.

Common situations: A session with an enormous message history; a hand-edited or future-format archive with a giant JSON entry; entry-limit config bypassed when calling readZipFileEntries.

Related errors


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