siyuan-note/siyuan · error

parse imported notebook conf [%s] failed: %w

Error message

parse imported notebook conf [%s] failed: %w

What it means

Thrown by validateImportedNotebookIdentities when the notebook's conf.json was read successfully but cannot be unmarshaled into conf.BoxConf via gulu.JSON.UnmarshalJSON. The JSON is either syntactically invalid or does not conform to the expected schema. The error wraps the unmarshal error with the boxID.

Source

Thrown at kernel/model/import.go:1057

	for _, entry := range dirs {
		if !entry.IsDir() || !ast.IsNodeIDPattern(entry.Name()) {
			continue
		}

		boxID := entry.Name()
		boxDir := filepath.Join(tmpDataPath, boxID)
		confPath := filepath.Join(boxDir, ".siyuan", "conf.json")
		backupPath := filepath.Join(boxDir, ".siyuan", notebookCryptoBackupFilename)

		var boxConf *conf.BoxConf
		if filelock.IsExist(confPath) {
			data, readErr := filelock.ReadFile(confPath)
			if readErr != nil {
				return nil, fmt.Errorf("read imported notebook conf [%s] failed: %w", boxID, readErr)
			}
			boxConf = conf.NewBoxConf()
			if unmarshalErr := gulu.JSON.UnmarshalJSON(data, boxConf); unmarshalErr != nil {
				return nil, fmt.Errorf("parse imported notebook conf [%s] failed: %w", boxID, unmarshalErr)
			}
		}

		var backup *conf.BoxEncryption
		if filelock.IsExist(backupPath) {
			backup, err = readBoxEncryptionFile(backupPath)
			if err != nil {
				return nil, fmt.Errorf("invalid imported notebook identity [%s]: %w", boxID, err)
			}
		}

		var boxCrypt *conf.BoxEncryption
		if boxConf != nil && boxConf.Encrypted {
			if boxConf.BoxCrypt != nil && validateBoxEncryption(boxConf.BoxCrypt) == nil {
				boxCrypt = boxConf.BoxCrypt
			} else {
				boxCrypt = backup
			}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Open the conf.json from the extracted Data.zip in a JSON validator to find syntax errors.
  2. Re-export the Data.zip from a compatible SiYuan version.
  3. If the schema changed between versions, upgrade or downgrade the source SiYuan to match the target version.
  4. Remove the corrupted notebook directory from the Data.zip and re-export just that notebook.
Defensive patterns

Strategy: validation

Validate before calling

// Validate conf.json structure before importing
func validateConfJSON(tmpDataPath, boxID string) error {
    confPath := filepath.Join(tmpDataPath, boxID, ".siyuan", "conf.json")
    if !filelock.IsExist(confPath) {
        return nil
    }
    data, err := filelock.ReadFile(confPath)
    if err != nil {
        return err
    }
    var test conf.BoxConf
    if err := gulu.JSON.UnmarshalJSON(data, &test); err != nil {
        return fmt.Errorf("notebook %s conf.json is invalid JSON: %w", boxID, err)
    }
    return nil
}

Try / catch

encryptedBoxIDs, err := validateImportedNotebookIdentities(tmpDataPath)
if err != nil {
    if strings.Contains(err.Error(), "parse imported notebook conf") {
        // conf.json is corrupt — suggest re-export or manual fix
        return fmt.Errorf("notebook config is corrupted, please re-export the Data archive")
    }
}

Prevention

When it happens

Trigger: Calling validateImportedNotebookIdentities where the conf.json content is valid bytes but invalid JSON, or valid JSON with fields that do not match the conf.BoxConf struct. The check is at import.go:1056-1058.

Common situations: conf.json truncated due to incomplete export. conf.json from an older or newer SiYuan version with an incompatible schema. Manual editing of conf.json that introduced JSON syntax errors. Encoding issues (BOM, wrong charset) in the file.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/702b2a49881ef42f. Report an issue: GitHub.