siyuan-note/siyuan · error

inspect imported notebook [%s] failed: %w

Error message

inspect imported notebook [%s] failed: %w

What it means

Thrown by validateImportedNotebookIdentities when hasEncryptedNotebookPayloadAtPath encounters an I/O error while walking the notebook directory tree. This function walks every file in the extracted notebook directory and reads the first 4 bytes of each to check for the encrypted-notebook data magic header. Any walk or read error is wrapped with the boxID and returned.

Source

Thrown at kernel/model/import.go:1087

		var boxCrypt *conf.BoxEncryption
		if boxConf != nil && boxConf.Encrypted {
			if boxConf.BoxCrypt != nil && validateBoxEncryption(boxConf.BoxCrypt) == nil {
				boxCrypt = boxConf.BoxCrypt
			} else {
				boxCrypt = backup
			}
			if boxCrypt == nil {
				return nil, fmt.Errorf("encrypted notebook [%s] has no valid identity", boxID)
			}
		} else if boxConf != nil && backup != nil {
			return nil, fmt.Errorf("notebook [%s] has conflicting normal and encrypted identities", boxID)
		} else if backup != nil {
			boxCrypt = backup
		}

		payloadFound, payloadErr := hasEncryptedNotebookPayloadAtPath(boxDir)
		if payloadErr != nil {
			return nil, fmt.Errorf("inspect imported notebook [%s] failed: %w", boxID, payloadErr)
		}
		if boxCrypt == nil && payloadFound {
			return nil, fmt.Errorf("imported notebook [%s] contains encrypted payload without identity", boxID)
		}
		if boxCrypt == nil {
			continue
		}

		if err = validateBoxEncryption(boxCrypt); err != nil {
			return nil, fmt.Errorf("invalid imported notebook identity [%s]: %w", boxID, err)
		}
		if filelock.IsExist(filepath.Join(util.DataDir, boxID)) && IsEncryptedBox(boxID) {
			return nil, fmt.Errorf("refuse to overwrite existing encrypted notebook [%s]", boxID)
		}
		encryptedBoxIDs = append(encryptedBoxIDs, boxID)
	}
	return encryptedBoxIDs, nil
}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Check permissions on all files and subdirectories within the notebook directory in the extracted Data.zip.
  2. Re-export the Data.zip to rule out archive corruption.
  3. Verify the temp extraction directory is on a healthy filesystem.
  4. Inspect the wrapped error (%w) for the specific I/O error and path that caused the failure.
Defensive patterns

Strategy: try-catch

Try / catch

encryptedBoxIDs, err := validateImportedNotebookIdentities(tmpDataPath)
if err != nil {
    if strings.Contains(err.Error(), "inspect imported notebook") {
        // I/O error during encrypted payload scan
        logging.LogErrorf("cannot scan notebook directory for encrypted payload: %s", err)
        // Suggest checking permissions or re-exporting
    }
}

Prevention

When it happens

Trigger: Calling validateImportedNotebookIdentities where hasEncryptedNotebookPayloadAtPath(boxDir) returns a non-nil error. The walk at crypto.go:122-147 can fail on directory access errors, file open errors, or read errors on individual files. The check is at import.go:1085-1088.

Common situations: Permission denied on a subdirectory or file within the extracted notebook. Filesystem errors on the temp volume. Files deleted between the directory listing and the walk (race with cleanup). Symlink loops causing infinite traversal. Special files (device files, pipes) that cannot be read.

Related errors


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