{"record":{"id":"344f26dba31cdf7d","repo":"siyuan-note/siyuan","slug":"create-history-directory-s-failed-w","errorCode":null,"errorMessage":"create history directory [%s] failed: %w","messagePattern":"create history directory \\[(.+?)\\] failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/history.go","lineNumber":900,"sourceCode":"\t\treturn errors.New(\"asset path must be a file\")\n\t}\n\treturn createAssetsHistory([]string{assetAbsPath})\n}\n\nfunc createAssetsHistory(assets []string) (err error) {\n\thistoryDir, err := getHistoryDir(HistoryOpUpdate)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"get history directory failed: %w\", err)\n\t}\n\n\tfor _, file := range assets {\n\t\tassetRelPath, relErr := filepath.Rel(filepath.Join(util.DataDir, \"assets\"), file)\n\t\tif relErr != nil || assetRelPath == \".\" || strings.HasPrefix(assetRelPath, \"..\"+string(filepath.Separator)) {\n\t\t\treturn errors.New(\"asset path must be under assets\")\n\t\t}\n\t\thistoryPath := filepath.Join(historyDir, \"assets\", assetRelPath)\n\t\tif err = os.MkdirAll(filepath.Dir(historyPath), 0755); err != nil {\n\t\t\treturn fmt.Errorf(\"create history directory [%s] failed: %w\", filepath.Dir(historyPath), err)\n\t\t}\n\n\t\tif err = filelock.Copy(file, historyPath); err != nil {\n\t\t\tif os.IsNotExist(err) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"copy asset [%s] to [%s] failed: %w\", file, historyPath, err)\n\t\t}\n\t}\n\n\tindexHistoryDir(filepath.Base(historyDir), util.NewLute())\n\treturn\n}\n\nfunc (box *Box) generateDocHistory0() {\n\tfiles := box.recentModifiedDocs()\n\tif 1 > len(files) {\n\t\treturn","sourceCodeStart":882,"sourceCodeEnd":918,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/afa823b6b4e4f183511e0bc0a3be93caa94c7c97/kernel/model/history.go#L882-L918","documentation":"createAssetsHistory (kernel/model/history.go:898-901) fails when os.MkdirAll cannot create the per-asset subdirectory inside the history tree; the target directory name is included in the message and the underlying error is chained with %w. Same environmental causes as any MkdirAll failure: permission denied, disk full, or a regular file occupying a path where a directory is needed.","triggerScenarios":"A previous history run left a regular file where a directory must now be created (e.g. history/<ts>-update/assets/foo exists as a file while a new snapshot needs history/.../assets/foo/bar.png); history/ not writable; ENOSPC while creating deep asset subpaths.","commonSituations":"Assets whose names collide across file/dir roles over time (photo.png as file, then photo.png/ as dir for child assets); permission or disk-space regressions between generation cycles.","solutions":["Inspect the directory named in the error; if a regular file occupies the path, remove or rename it (with the kernel stopped if it is in use)","Fix write permissions and free disk space on the workspace volume as with any mkdir failure","After repairing the tree, trigger /api/history/reindexHistory so the history index matches the fixed layout"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if fi, err := os.Stat(filepath.Dir(targetHistoryPath)); err == nil && !fi.IsDir() {\n    return fmt.Errorf(\"regular file occupies directory path: %s\", filepath.Dir(targetHistoryPath))\n}","typeGuard":null,"tryCatchPattern":"err := createAssetsHistory(files)\nif err != nil && strings.Contains(err.Error(), \"create history directory\") {\n    if errors.Is(err, fs.ErrExist) || errors.Is(err, fs.ErrNotDir) { /* remove conflicting file entry */ }\n    if errors.Is(err, fs.ErrPermission) { /* fix perms */ }\n}","preventionTips":["Avoid asset names that alternate between file and directory roles in the same path","Keep history/ writable and disk-space monitored","Reindex history after repairing the tree"],"tags":["filesystem","mkdir","permissions","history","disk-full"],"backgroundTag":"directory-create-failed","analyzedSha":"afa823b6b4e4f183511e0bc0a3be93caa94c7c97","analyzedAt":"2026-08-18T17:04:10.865Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}