chatboxai/chatbox · error
ZIP archive is missing its central directory
Error message
ZIP archive is missing its central directory
What it means
Thrown by validateZipEndOfCentralDirectory after scanning the file's tail for the EOCD signature (0x50 0x4b 0x05 0x06) and finding no candidate whose declared comment length lines up with the tail size. Without a valid EOCD the central directory cannot be located, so the archive is treated as corrupt or non-ZIP.
Source
Thrown at src/renderer/packages/backup/zip.ts:188
async function validateZipEndOfCentralDirectory(file: File) {
const minimumRecordSize = 22
const maximumCommentSize = 65_535
if (file.size < minimumRecordSize) throw new Error('ZIP archive is truncated')
const tailSize = Math.min(file.size, minimumRecordSize + maximumCommentSize)
const tail = new Uint8Array(await file.slice(file.size - tailSize).arrayBuffer())
let recordOffset = -1
for (let index = tail.length - minimumRecordSize; index >= 0; index--) {
if (tail[index] === 0x50 && tail[index + 1] === 0x4b && tail[index + 2] === 0x05 && tail[index + 3] === 0x06) {
const candidateView = new DataView(tail.buffer, tail.byteOffset + index, tail.length - index)
const commentLength = candidateView.getUint16(20, true)
if (index + minimumRecordSize + commentLength === tail.length) {
recordOffset = index
break
}
}
}
if (recordOffset < 0) throw new Error('ZIP archive is missing its central directory')
const view = new DataView(tail.buffer, tail.byteOffset + recordOffset, tail.length - recordOffset)
const centralDirectorySize = view.getUint32(12, true)
const centralDirectoryOffset = view.getUint32(16, true)
if (centralDirectoryOffset + centralDirectorySize > file.size - (tail.length - recordOffset)) {
throw new Error('ZIP archive central directory is invalid')
}
}
function combineChunks(chunks: Uint8Array[], totalSize: number): Uint8Array {
const output = new Uint8Array(totalSize)
let offset = 0
for (const chunk of chunks) {
output.set(chunk, offset)
offset += chunk.length
}
return output
}
View on GitHub (pinned to 81571269ad)
Solutions
- Verify the file is actually a ZIP (magic bytes 'PK' at offset 0) before importing.
- Re-download or re-export the backup.
- If repairing, use a zip-repair tool to rebuild the central directory.
Example fix
// before
await readZipFileEntries(file, onEntry, options)
// after
const head = new Uint8Array(await file.slice(0, 4).arrayBuffer())
const isZip = head[0] === 0x50 && head[1] === 0x4b
if (!isZip) throw new Error('Selected file is not a ZIP archive')
await readZipFileEntries(file, onEntry, options) Defensive patterns
Strategy: try-catch
Validate before calling
async function hasZipMagic(file: File): Promise<boolean> {
if (file.size < 4) return false
const head = new Uint8Array(await file.slice(0, 4).arrayBuffer())
return head[0] === 0x50 && head[1] === 0x4b
} Try / catch
try {
await readZipFileEntries(file, onEntry, options)
} catch (error) {
if (/missing its central directory/.test((error as Error).message)) notifyUser('Backup archive is corrupt')
throw error
} Prevention
- Check the 'PK' magic bytes at offset 0 before invoking the reader.
- Re-download or re-export when an archive fails this check; do not retry the same bytes.
- Verify archive integrity (size/transfer checksum) before import.
When it happens
Trigger: No valid EOCD record found in the last (22 + 65535) bytes of the file — e.g. the file isn't a ZIP at all, or the EOCD was truncated or overwritten.
Common situations: User picks a non-ZIP file; archive corrupted in transit; archive truncated so the EOCD is missing; the comment-length field is corrupted.
Related errors
- Unsafe ZIP entry path: ${path}
- Duplicate ZIP entry: ${entry.path}
- ZIP archive is truncated
- ZIP archive central directory is invalid
- No readable text content found in EPUB file
AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12).
Data as JSON: /api/errors/e4bd2c03e3c0e81b.
Report an issue: GitHub.