BookStackApp/BookStack · error · ZipImportException
Parent book required for chapter import.
Error message
Parent book required for chapter import.
What it means
ZipImportRunner::run() requires that a chapter export (ZipExportChapter) is imported with a parent that is a Book instance. If $parent is null or any other entity type, it throws ZipImportException 'Parent book required for chapter import.' Chapters can only live directly under books in BookStack's hierarchy.
Source
Thrown at app/Exports/ZipExports/ZipImportRunner.php:74
$errors = (new ZipExportValidator($reader))->validate();
if ($errors) {
throw new ZipImportException([
trans('errors.import_validation_failed'),
...$errors,
]);
}
try {
$exportModel = $reader->decodeDataToExportModel();
} catch (ZipExportException $e) {
throw new ZipImportException([$e->getMessage()]);
}
// Validate parent type
if ($exportModel instanceof ZipExportBook && ($parent !== null)) {
throw new ZipImportException(["Must not have a parent set for a Book import."]);
} else if ($exportModel instanceof ZipExportChapter && !($parent instanceof Book)) {
throw new ZipImportException(["Parent book required for chapter import."]);
} else if ($exportModel instanceof ZipExportPage && !($parent instanceof Book || $parent instanceof Chapter)) {
throw new ZipImportException(["Parent book or chapter required for page import."]);
}
$this->ensurePermissionsPermitImport($exportModel, $parent);
if ($exportModel instanceof ZipExportBook) {
$entity = $this->importBook($exportModel, $reader);
} else if ($exportModel instanceof ZipExportChapter) {
$entity = $this->importChapter($exportModel, $parent, $reader);
} else {
$entity = $this->importPage($exportModel, $parent, $reader);
}
$this->references->replaceReferences();
$reader->close();
$this->cleanup();View on GitHub (pinned to 18f8469a1c)
Solutions
- Pass a valid Book id as parent_id in the import API request.
- Select a Book as the parent in the import form.
- Fetch the correct book id (e.g. via the search/API) before running the import.
Example fix
// before
POST /import {"zip_id": 7}
// after
POST /import {"zip_id": 7, "parent_id": 12} // 12 = a Book id Defensive patterns
Strategy: validation
Validate before calling
$data = json_decode($zip->getFromName('data.json') ?: '', true);
if (isset($data['chapter']) && (!$parent instanceof \BookStack\Entities\Models\Book)) {
throw new \InvalidArgumentException('Chapter imports require a Book parent');
} Type guard
function chapterParentOk($parent): bool {
return $parent instanceof \BookStack\Entities\Models\Book;
} Try / catch
try {
$runner->run($import, $parent);
} catch (\BookStack\Exceptions\ZipImportException $e) {
// resolve a Book id and retry the import
} Prevention
- Resolve and verify the target book id before importing chapters.
- UI: always pick a Book (not another chapter) as parent.
- API scripts: validate parent entity type via the API before calling import.
When it happens
Trigger: Importing a chapter ZIP with no parent selected, or with a Chapter/Page/Shelf passed as parent.
Common situations: API scripts forgetting parent_id for chapter imports; selecting the wrong parent in the import UI; automation that treats chapters like books.
Related errors
- Must not have a parent set for a Book import.
- Parent book or chapter required for page import.
- errors.api_bad_authorization_format
- errors.api_user_token_not_found
- errors.import_zip_cant_decode_data
AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02).
Data as JSON: /api/errors/fd078da5ce166878.
Report an issue: GitHub.