BookStackApp/BookStack · error · ZipExportException
errors.import_zip_cant_decode_data
Error message
errors.import_zip_cant_decode_data
What it means
BookStack's ZIP import reader throws ZipExportException with the localized message 'errors.import_zip_cant_decode_data' when the uploaded ZIP archive does not contain a 'data.json' entry at its root. ZipExportReader::readData() calls $this->zip->statName('data.json') and treats a false result as an unreadable/invalid export. This is the reader's way of rejecting archives that are not valid BookStack ZIP exports.
Source
Thrown at app/Exports/ZipExports/ZipExportReader.php:63
public function close(): void
{
if ($this->open) {
$this->zip->close();
$this->open = false;
}
}
/**
* @throws ZipExportException
*/
public function readData(): array
{
$this->open();
$info = $this->zip->statName('data.json');
if ($info === false) {
throw new ZipExportException(trans('errors.import_zip_cant_decode_data'));
}
$maxSize = max(intval(config()->get('app.upload_limit')), 1) * 1000000;
if ($info['size'] > $maxSize) {
throw new ZipExportException(trans('errors.import_zip_data_too_large'));
}
// Validate json data exists, including metadata
$jsonData = $this->zip->getFromName('data.json') ?: '';
$importData = json_decode($jsonData, true);
if (!$importData) {
throw new ZipExportException(trans('errors.import_zip_cant_decode_data'));
}
return $importData;
}
public function fileExists(string $fileName): boolView on GitHub (pinned to 18f8469a1c)
Solutions
- Verify the ZIP contains a root-level data.json (unzip -l export.zip).
- Re-zip so data.json sits at the archive root, not inside a nested directory.
- Regenerate the export from the source BookStack instance instead of hand-editing the archive.
- Check the upload wasn't truncated/corrupted (compare file size/checksum).
Example fix
// before (importing a zip where data.json is nested) zip: my-export.zip -> my-export/data.json // after zip: my-export.zip -> data.json
Defensive patterns
Strategy: validation
Validate before calling
$zip = new ZipArchive();
if ($zip->open($path) === true) {
if ($zip->locateName('data.json', ZipArchive::FL_NODIR) === false) {
throw new \InvalidArgumentException('ZIP is not a BookStack export: missing data.json at root');
}
}
$zip->close(); Type guard
function isBookStackExportZip(string $path): bool {
$zip = new ZipArchive();
if ($zip->open($path) !== true) return false;
$ok = $zip->locateName('data.json', ZipArchive::FL_NODIR) !== false;
$zip->close();
return $ok;
} Try / catch
try {
$model = $reader->decodeDataToExportModel();
} catch (\BookStack\Exports\ZipExports\ZipExportException $e) {
if (trans('errors.import_zip_cant_decode_data') === $e->getMessage()) {
// report invalid archive to the user
}
} Prevention
- Always create ZIPs from the export folder contents (not the parent folder) so data.json is at root.
- List archive contents (unzip -l) before importing.
- Never hand-truncate or partially download export ZIPs.
- Keep export and import on compatible BookStack versions.
When it happens
Trigger: Importing a ZIP that has no data.json at the root (e.g. a plain file archive, an export re-zipped so data.json ended up in a subfolder, or a truncated/corrupt upload where the central directory lost the entry).
Common situations: Users re-compress exported files with Finder/Explorer nesting a folder inside the zip; partially uploaded archives; renaming .zip exports; attempting to import a BookStack v5-style zip into an older import path.
Related errors
- errors.import_zip_data_too_large
- Could not identify content in ZIP file data.
- errors.import_validation_failed
- Must not have a parent set for a Book import.
- Parent book required for chapter import.
AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02).
Data as JSON: /api/errors/13f152c5f4d63502.
Report an issue: GitHub.