{"record":{"id":"1dbdeb2706d55c76","repo":"siyuan-note/siyuan","slug":"cannot-allocate-a-replacement-history-directory","errorCode":null,"errorMessage":"cannot allocate a replacement history directory","messagePattern":"cannot allocate a replacement history directory","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/asset_relink.go","lineNumber":479,"sourceCode":"\t\t}\n\t}\n\tp.result.References = append(p.result.References, ref)\n\treturn nil\n}\n\nfunc newAssetRelinkHistoryDir() (string, error) {\n\tif err := os.MkdirAll(util.HistoryDir, 0755); err != nil {\n\t\treturn \"\", err\n\t}\n\tfor offset := 0; offset < 1000; offset++ {\n\t\tdir := filepath.Join(util.HistoryDir, time.Now().Add(time.Duration(offset)*time.Second).Format(\"2006-01-02-150405\")+\"-\"+HistoryOpReplace)\n\t\tif err := os.Mkdir(dir, 0755); err == nil {\n\t\t\treturn dir, nil\n\t\t} else if !os.IsExist(err) {\n\t\t\treturn \"\", err\n\t\t}\n\t}\n\treturn \"\", errors.New(\"cannot allocate a replacement history directory\")\n}\n\nfunc validateRelinkStoragePath(abs string) error {\n\treal, err := filepath.EvalSymlinks(abs)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdataRoot, err := filepath.EvalSymlinks(util.DataDir)\n\tif err != nil || !gulu.File.IsSubPath(dataRoot, real) {\n\t\treturn fmt.Errorf(\"resource escapes the data directory: %s\", abs)\n\t}\n\trel, err := filepath.Rel(dataRoot, real)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfirst, _, _ := strings.Cut(filepath.ToSlash(rel), \"/\")\n\tif ast.IsNodeIDPattern(first) && IsEncryptedBox(first) {\n\t\treturn errors.New(\"encrypted resources are not supported\")","sourceCodeStart":461,"sourceCodeEnd":497,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/asset_relink.go#L461-L497","documentation":"Before applying a relink, the planner creates a timestamped backup directory under the history dir named <time>-<op>. It tries up to 1000 successive seconds for a free name; if every Mkdir collides with an existing directory (or clock anomalies make all names taken), it gives up with this error rather than risk overwriting an existing history entry.","triggerScenarios":"newAssetRelinkHistoryDir is called from apply; all 1000 candidate timestamp directories already exist in data/history/ — e.g. thousands of replace operations created dirs within the same second-range, or clock skew keeps regenerating identical names that pre-exist.","commonSituations":"System clock set far ahead so future-timestamped dirs already exist; history dir polluted by many manual/test entries; the same relink applied repeatedly across clock jumps.","solutions":["Clean up old/obsolete entries in data/history/ (or archive them elsewhere)","Correct the system clock (NTP sync) if it is skewed relative to existing history dirs","Check for existing dirs matching 2006-01-02-150405-replace and remove future-dated collisions","Retry after freeing/normalizing the history directory"],"exampleFix":"// before\n// data/history contains 2026-09-18-120000-replace ... many future dirs\n// after\nmv data/history/2026-09-18-120000-replace /archive/history-backup/\n// re-run the relink apply","handlingStrategy":"retry","validationCode":"// pre-check history dir for colliding future-dated replace dirs\npattern := time.Now().Format(\"2006-01-02\")\nmatches, _ := filepath.Glob(filepath.Join(historyDir, pattern+\"*-replace\"))\nif len(matches) > 900 {\n\t// archive/clean old history entries first\n}","typeGuard":null,"tryCatchPattern":"// retry after cleaning the history directory\nif err := plan.Apply(); err != nil {\n\tif err.Error() == \"cannot allocate a replacement history directory\" {\n\t\t// archive old data/history entries, fix clock, then retry once\n\t}\n\treturn err\n}","preventionTips":["Keep the system clock NTP-synced so timestamped history names do not collide with future entries","Regularly archive/prune data/history to avoid tens of thousands of entries","Do not manually pre-create directories in data/history"],"tags":["history","filesystem","collision","backup"],"backgroundTag":"file-already-exists","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}