{"record":{"id":"16c0d0ca682721dd","repo":"siyuan-note/siyuan","slug":"refuse-to-overwrite-existing-encrypted-notebook","errorCode":null,"errorMessage":"refuse to overwrite existing encrypted notebook [%s]","messagePattern":"refuse to overwrite existing encrypted notebook \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/import.go","lineNumber":1100,"sourceCode":"\t\t\tboxCrypt = backup\n\t\t}\n\n\t\tpayloadFound, payloadErr := hasEncryptedNotebookPayloadAtPath(boxDir)\n\t\tif payloadErr != nil {\n\t\t\treturn nil, fmt.Errorf(\"inspect imported notebook [%s] failed: %w\", boxID, payloadErr)\n\t\t}\n\t\tif boxCrypt == nil && payloadFound {\n\t\t\treturn nil, fmt.Errorf(\"imported notebook [%s] contains encrypted payload without identity\", boxID)\n\t\t}\n\t\tif boxCrypt == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tif err = validateBoxEncryption(boxCrypt); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid imported notebook identity [%s]: %w\", boxID, err)\n\t\t}\n\t\tif filelock.IsExist(filepath.Join(util.DataDir, boxID)) && IsEncryptedBox(boxID) {\n\t\t\treturn nil, fmt.Errorf(\"refuse to overwrite existing encrypted notebook [%s]\", boxID)\n\t\t}\n\t\tencryptedBoxIDs = append(encryptedBoxIDs, boxID)\n\t}\n\treturn encryptedBoxIDs, nil\n}\n\nfunc ImportData(zipPath string) (err error) {\n\tutil.PushEndlessProgress(Conf.Language(73))\n\tdefer util.ClearPushProgress(100)\n\n\tlockSync()\n\tdefer unlockSync()\n\n\tlogging.LogInfof(\"import data from [%s]\", zipPath)\n\tbaseName := filepath.Base(zipPath)\n\text := filepath.Ext(baseName)\n\tbaseName = strings.TrimSuffix(baseName, ext)\n\tunzipPath := filepath.Join(filepath.Dir(zipPath), baseName)","sourceCodeStart":1082,"sourceCodeEnd":1118,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/import.go#L1082-L1118","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Rename or remove the existing encrypted notebook directory from data/ before importing.","Export the existing encrypted notebook first as a backup, then unmount and delete it before importing.","If importing on a fresh workspace, ensure no stale notebook directories exist in the data directory.","Edit the boxID in the Data.zip's notebook directory and conf.json to avoid the collision (advanced, requires consistent ID changes)."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before importing, check for ID collisions with existing encrypted notebooks\nfunc checkEncryptedBoxCollision(boxIDs []string) error {\n    for _, boxID := range boxIDs {\n        existingPath := filepath.Join(util.DataDir, boxID)\n        if filelock.IsExist(existingPath) && model.IsEncryptedBox(boxID) {\n            return fmt.Errorf(\"encrypted notebook %s already exists — rename or remove it first\", boxID)\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"encryptedBoxIDs, err := validateImportedNotebookIdentities(tmpDataPath)\nif err != nil {\n    if strings.Contains(err.Error(), \"refuse to overwrite existing encrypted notebook\") {\n        // Extract boxID and prompt user to rename/remove existing notebook\n        boxID := extractBoxIDFromError(err.Error())\n        return fmt.Errorf(\"encrypted notebook %s already exists — export and remove it before importing\", boxID)\n    }\n}","preventionTips":["Before importing Data.zip, check if any notebook IDs in the archive match existing encrypted notebooks.","Export and back up existing encrypted notebooks before importing a Data.zip that might overwrite them.","Import into a fresh workspace to avoid ID collisions.","Rename the boxID directory in the Data.zip if you need to import alongside an existing notebook with the same ID."],"tags":["encryption","import","data-zip","safety","overwrite"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}