siyuan-note/siyuan · error

Conf.Language(199)

Error message

Conf.Language(199)

What it means

ImportSYNotebookBundle imports a multi-notebook bundle (.sy.zip containing a bundle manifest). While scanning the archive for a `*/manifest.json` bundle entry, it found a manifest path that is structurally invalid: the candidate root folder is empty, nested (contains '/'), or a second manifest was found after one was already accepted. The library rejects such archives because a bundle must contain exactly one top-level folder holding exactly one manifest.

Source

Thrown at kernel/model/notebook_bundle.go:218

// ImportSYNotebookBundle 导入批量笔记本包。普通 .sy.zip 返回 bundle=false,由原有导入流程继续处理。
func ImportSYNotebookBundle(zipPath string) (boxIDs []string, bundle bool, err error) {
	archive, openErr := zip.OpenReader(zipPath)
	if nil != openErr {
		err = openErr
		return
	}
	var manifestData []byte
	rootName := ""
	manifestSuffix := "/" + syNotebookBundleManifestPath
	for _, file := range archive.File {
		if !strings.HasSuffix(file.Name, manifestSuffix) {
			continue
		}
		candidateRoot := strings.TrimSuffix(file.Name, manifestSuffix)
		if candidateRoot == "" || strings.Contains(candidateRoot, "/") || rootName != "" {
			_ = archive.Close()
			return nil, true, errors.New(Conf.Language(199))
		}
		reader, readErr := file.Open()
		if nil != readErr {
			_ = archive.Close()
			return nil, true, readErr
		}
		manifestData, readErr = io.ReadAll(reader)
		_ = reader.Close()
		if nil != readErr {
			_ = archive.Close()
			return nil, true, readErr
		}
		rootName = candidateRoot
	}
	_ = archive.Close()
	if rootName == "" {
		return nil, false, nil
	}

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Rebuild the bundle so the zip contains exactly one top-level folder with manifest.json directly inside it and no other manifest.json anywhere in the archive
  2. Open the .sy.zip and inspect entry names (unzip -l) to find duplicate or nested manifest.json files and remove the extras
  3. Re-export the bundle from SiYuan's export-bundle feature instead of manually repackaging
  4. If the file is a plain single-notebook .sy.zip (no manifest), do not call ImportSYNotebookBundle; use the normal single-notebook import path, which is tried when bundle=false

Example fix

// before: zip layout 'outer/inner/manifest.json' or two manifests
// after: exactly one root folder
// bundle/
//   manifest.json
//   notebooks/Notebook1.sy.zip
Defensive patterns

Strategy: validation

Validate before calling

// Inspect zip entries before import (Node.js example)
const entries = (await getZipEntryNames(bundlePath));
const manifests = entries.filter(n => n.endsWith('/manifest.json'));
if (manifests.length !== 1) throw new Error('bundle must contain exactly one manifest');
const root = manifests[0].slice(0, -('/manifest.json'.length));
if (!root || root.includes('/')) throw new Error('manifest must sit in a single top-level folder');

Try / catch

try {
  const { boxIDs, bundle } = await importSYNotebookBundle(zipPath);
  if (!bundle) return importSingleNotebook(zipPath); // bundle=false means plain .sy.zip
} catch (e) {
  if (e.message.includes('invalid') || isLocalizedBundleError(e)) showUserHint('Rebuild the bundle: exactly one top-level folder with one manifest.json');
  else throw e;
}

Prevention

When it happens

Trigger: Calling ImportSYNotebookBundle (via the import .sy.zip API endpoint) on a zip where: (a) the manifest sits at the archive root (candidateRoot == "", e.g. 'manifest.json' with no folder prefix is matched by suffix '/manifest.json'? actually an entry named exactly with empty prefix), (b) a manifest exists in a nested subfolder like 'outer/inner/manifest.json', or (c) the zip contains two or more manifest files in different top-level folders.

Common situations: Hand-assembled or re-zipped bundles where the zip tool wrapped folders twice (e.g. 'Bundle/Bundle/manifest.json'), bundles produced by old/custom export scripts that place the manifest at the archive root, or concatenated archives that accidentally include manifests from multiple exports.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/7da5e1b326472deb. Report an issue: GitHub.