siyuan-note/siyuan · error
rename path failed
Error message
rename path failed
What it means
This is a legacy 'rename doc' path in import.go that moves previously exported/imported paths within a notebook (oldPaths -> renamePaths mapping, sorted shallowest-first). If filelock.Rename fails for any pair, the function logs the underlying OS error and replaces it with the generic message 'rename path failed'. The real cause (locked file, missing source, cross-device link) is only visible in the kernel log.
Solutions
- Check the kernel log for the 'rename path from [...] to [...] failed' line to find the real OS error and the specific paths involved.
- Ensure no other SiYuan instance / antivirus locks files in the workspace's data directory, then retry the import.
- Verify the source .sy files referenced by oldPaths exist; restore them or re-export the package.
- Run the kernel with sufficient permissions over the workspace, and keep data on a local filesystem rather than a network share.
Example fix
// before
if err = filelock.Rename(oldPath, newPath); err != nil {
err = errors.New("rename path failed")
}
// after
if err = filelock.Rename(oldPath, newPath); err != nil {
err = fmt.Errorf("rename path from [%s] to [%s] failed: %w", oldPath, newPath, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
for (const p of [oldPath, newPath]) {
if (!fs.existsSync(p) && fs.existsSync(oldPath)) { throw new Error(`missing rename source ${oldPath}`); }
} Try / catch
try {
await importSY(boxID, src);
} catch (e) {
if (e.msg === 'rename path failed') {
console.error('Check kernel log for "rename path from ... failed"; close other SiYuan instances and retry');
}
throw e;
} Prevention
- Keep only one kernel instance per workspace
- Exclude the workspace data dir from antivirus real-time locking (especially on Windows)
- Keep the workspace on a local filesystem, not network shares
- Do not manually delete .sy files referenced by import packages
When it happens
Trigger: ImportSY processing a package whose payload includes path-rename operations, when filelock.Rename(oldPath, newPath) fails — e.g. the source .sy file is missing, the target path already exists, file locks/permissions block the move on Windows, or the data dir is on a different filesystem.
Common situations: 1) Antivirus/indexer (or another SiYuan instance) holds the file open on Windows, breaking rename. 2) Stale renamePaths referencing documents deleted between export and import. 3) Workspace on a network mount where rename semantics differ. 4) Permission mismatch after copying a workspace with different ownership.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- Move notebook [ ] file [ ] failed
- 0
- copy data failed
- errors.New(msg) with Conf.Language(5) template: move…
- Export failed
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/553e46767a5b5129.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/import.go:1023
buf.WriteString("/")
}
}
newPath := buf.String()
renamePaths[originalPath] = filepath.Join(unzipRootPath, newPath)
}
var oldPaths []string
for oldPath := range renamePaths {
oldPaths = append(oldPaths, oldPath)
}
sort.Slice(oldPaths, func(i, j int) bool {
return strings.Count(oldPaths[i], string(os.PathSeparator)) < strings.Count(oldPaths[j], string(os.PathSeparator))
})
for i, oldPath := range oldPaths {
newPath := renamePaths[oldPath]
if err = filelock.Rename(oldPath, newPath); err != nil {
logging.LogErrorf("rename path from [%s] to [%s] failed: %s", oldPath, renamePaths[oldPath], err)
err = errors.New("rename path failed")
return
}
delete(renamePaths, oldPath)
var toRemoves []string
newRenamedPaths := map[string]string{}
for oldP, newP := range renamePaths {
if strings.HasPrefix(oldP, oldPath) {
renamedOldP := strings.Replace(oldP, oldPath, newPath, 1)
newRenamedPaths[renamedOldP] = newP
toRemoves = append(toRemoves, oldPath)
}
}
for _, toRemove := range toRemoves {
delete(renamePaths, toRemove)
}
maps.Copy(renamePaths, newRenamedPaths)
for j := i + 1; j < len(oldPaths); j++ {View on GitHub (pinned to 9f775e8a12)