siyuan-note/siyuan · error
content template [ ] is not a regular file
Error message
content template [%s] is not a regular file
What it means
After resolving symlinks, resolveDocContentTemplatePath stats the real path and requires it to be a regular file (os.Stat + Mode().IsRegular()). This same error is also returned when os.Stat itself fails. Directories, devices, fifos, or broken entries under templates/ cannot be used as content templates.
Solutions
- Point templatePath at a regular .md file, not a directory or special file.
- Re-create the symlink or restore the missing target file, then retry.
- Check os.Stat manually on <data>/templates/<templatePath> to see whether it exists and what kind of entry it is.
Example fix
// before templatePath := "templates-dir" // a directory // after templatePath := "templates-dir/index.md"
Defensive patterns
Strategy: validation
Validate before calling
const st = fs.statSync(process.env.SIYUAN_DATA + "/templates/" + templatePath);
if (!st.isFile()) throw new Error("template path is not a regular file"); Try / catch
try {
await applyDocContentTemplate(boxID, templatePath);
} catch (e) {
if (String(e).includes("not a regular file")) {
// fall back to directory listing or ask user to select a file
} else { throw e; }
} Prevention
- Never pass a directory as a template path; always target a concrete .md file
- Check for broken symlinks when templates are managed by dotfile tools
- Stat the path before the API call when the path comes from dynamic input
When it happens
Trigger: Passing a directory name inside <data>/templates/ as templatePath; the path is a symlink whose target vanished (EvalSymlinks succeeded but Stat failed), or the file was deleted between checks; the entry is a special file.
Common situations: Selecting a template subfolder instead of a file; symlinked template directories whose target was unmounted; race where the file is removed while the template is being applied.
Related errors
- cannot write a template directory
- content template path is outside templates directory
- content template [ ] not found
- createDocTree requires at least one document
- hidden template paths are reserved
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/59ce1684485701f5.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/template.go:1240
templateRoot := filepath.Join(util.DataDir, "templates")
absPath := filepath.Join(templateRoot, cleanPath)
if !gulu.File.IsSubPath(templateRoot, absPath) {
return "", errors.New("content template path is outside templates directory")
}
if !filelock.IsExist(absPath) {
return "", fmt.Errorf("content template [%s] not found", templatePath)
}
realRoot, err := filepath.EvalSymlinks(templateRoot)
if nil != err {
return "", err
}
realPath, err := filepath.EvalSymlinks(absPath)
if nil != err {
return "", err
}
info, err := os.Stat(realPath)
if nil != err || !info.Mode().IsRegular() {
return "", fmt.Errorf("content template [%s] is not a regular file", templatePath)
}
if !gulu.File.IsSubPath(realRoot, realPath) {
return "", errors.New("content template path is outside templates directory")
}
return realPath, nil
}
// CreateTemplate 在 <data>/templates/ 下创建模板文件。name 不含扩展名,content 为 markdown 文本。
// overwrite=false 且文件已存在时返回 code=1(与 DocSaveAsTemplate 一致)。
func CreateTemplate(name, content string, overwrite bool) (code int, err error) {
name = util.FilterFileName(name) + ".md"
name = util.TruncateLenFileName(name)
savePath := filepath.Join(util.DataDir, "templates", name)
if filelock.IsExist(savePath) {
if !overwrite {
code = 1
return
}View on GitHub (pinned to 9f775e8a12)