siyuan-note/siyuan · error

parse imported notebook conf

Error message

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

What it means

In validateImportedNotebookIdentities, after successfully reading an imported notebook's .siyuan/conf.json, the JSON must unmarshal into a conf.BoxConf. If the content is not valid JSON or has an incompatible shape, the function returns 'parse imported notebook conf [%s] failed' wrapping the unmarshal error, because boxConf fields (including Encrypted/BoxCrypt identity) cannot be trusted.

Solutions

  1. Open the imported notebook's .siyuan/conf.json and validate it as JSON (e.g. jq .); fix syntax errors if hand-edited.
  2. Re-export or re-download the notebook archive from the source workspace to get an intact conf.json.
  3. If only that notebook is corrupt, remove it from the import set, import the rest, then restore the notebook from a SiYuan snapshot/history backup.
  4. Compare with a valid conf.json from a working notebook to restore required fields (name, encrypted, etc.).
Defensive patterns

Strategy: validation

Validate before calling

const raw = await fs.promises.readFile(path.join(boxDir, '.siyuan', 'conf.json'), 'utf8');
JSON.parse(raw); // throws SyntaxError before the API call if the conf is malformed

Type guard

function isValidBoxConf(v) {
  return v !== null && typeof v === 'object' && !Array.isArray(v) && typeof v.name === 'string';
}

Try / catch

try {
  await importData(src);
} catch (e) {
  if (/parse imported notebook conf/.test(e.msg)) {
    console.error('Validate/repair .siyuan/conf.json JSON, or re-export the notebook');
  }
  throw e;
}

Prevention

When it happens

Trigger: ImportData importing a notebook whose .siyuan/conf.json is corrupt, truncated, hand-edited to invalid JSON, or produced by an incompatible tool/older format that gulu.JSON.UnmarshalJSON cannot decode into conf.BoxConf.

Common situations: 1) Archive extraction truncated by low disk space. 2) conf.json edited manually and saved with a syntax error. 3) Third-party tool writing a differently shaped conf.json. 4) Binary corruption from a failed sync/transfer.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/702b2a49881ef42f. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/import.go:1340

	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 9f775e8a12)