siyuan-note/siyuan · error

refuse to overwrite existing encrypted notebook [%s]

Error message

refuse to overwrite existing encrypted notebook [%s]

What it means

Thrown by validateImportedNotebookIdentities as a safety guard: if a directory with the same boxID already exists in the live data directory (util.DataDir) AND that existing notebook is currently encrypted, the import is refused. This prevents silently overwriting an existing encrypted notebook's data, which could cause permanent data loss since the overwritten encryption state would be unrecoverable. The check uses both filelock.IsExist and IsEncryptedBox.

Source

Thrown at kernel/model/import.go:1100

			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
}

func ImportData(zipPath string) (err error) {
	util.PushEndlessProgress(Conf.Language(73))
	defer util.ClearPushProgress(100)

	lockSync()
	defer unlockSync()

	logging.LogInfof("import data from [%s]", zipPath)
	baseName := filepath.Base(zipPath)
	ext := filepath.Ext(baseName)
	baseName = strings.TrimSuffix(baseName, ext)
	unzipPath := filepath.Join(filepath.Dir(zipPath), baseName)

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Rename or remove the existing encrypted notebook directory from data/ before importing.
  2. Export the existing encrypted notebook first as a backup, then unmount and delete it before importing.
  3. If importing on a fresh workspace, ensure no stale notebook directories exist in the data directory.
  4. Edit the boxID in the Data.zip's notebook directory and conf.json to avoid the collision (advanced, requires consistent ID changes).
Defensive patterns

Strategy: validation

Validate before calling

// Before importing, check for ID collisions with existing encrypted notebooks
func checkEncryptedBoxCollision(boxIDs []string) error {
    for _, boxID := range boxIDs {
        existingPath := filepath.Join(util.DataDir, boxID)
        if filelock.IsExist(existingPath) && model.IsEncryptedBox(boxID) {
            return fmt.Errorf("encrypted notebook %s already exists — rename or remove it first", boxID)
        }
    }
    return nil
}

Try / catch

encryptedBoxIDs, err := validateImportedNotebookIdentities(tmpDataPath)
if err != nil {
    if strings.Contains(err.Error(), "refuse to overwrite existing encrypted notebook") {
        // Extract boxID and prompt user to rename/remove existing notebook
        boxID := extractBoxIDFromError(err.Error())
        return fmt.Errorf("encrypted notebook %s already exists — export and remove it before importing", boxID)
    }
}

Prevention

When it happens

Trigger: Calling validateImportedNotebookIdentities (via ImportData) where the Data.zip contains an encrypted notebook whose boxID matches an existing encrypted notebook in the workspace. The check is at import.go:1099-1101.

Common situations: Importing a Data.zip that includes a notebook with the same ID as one already in the workspace. Re-importing after a failed or partial import left an encrypted notebook directory. Importing a backup from the same workspace (IDs collide). Copying Data.zip between instances that share notebook IDs.

Related errors


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