siyuan-note/siyuan · error
invalid template source file
Error message
invalid template source file
What it means
readTemplateSource loads the content of an existing template for the 'read' action. Before reading it requires the path to be a regular file (not a directory, device, fifo, etc.) and no larger than 8 MiB; failing either check yields 'invalid template source file'. This guards against reading non-file objects and against buffering oversized content.
Source
Thrown at kernel/model/template_manage.go:156
})
} else {
if info.Size() > maxTemplateSourceSize {
return "", errors.New("template source is too large")
}
var content []byte
content, err = root.ReadFile(p)
h.Write(content)
}
return fmt.Sprintf("%x", h.Sum(nil)), err
}
func readTemplateSource(root *os.Root, p string) (string, error) {
info, err := root.Stat(p)
if err != nil {
return "", err
}
if !info.Mode().IsRegular() || info.Size() > maxTemplateSourceSize {
return "", errors.New("invalid template source file")
}
content, err := root.ReadFile(p)
if err != nil {
return "", err
}
if !utf8.Valid(content) {
return "", errors.New("template source is not UTF-8")
}
return string(content), nil
}
// 同目录临时文件写入完成后替换,写入失败时保留原模板。
func writeTemplateSource(root *os.Root, p, content string, create bool) error {
if !utf8.ValidString(content) {
return errors.New("invalid template source")
}
if create {
file, err := root.OpenFile(p, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644)View on GitHub (pinned to 8641553a1f)
Solutions
- Check what is actually at the path: if it is a directory, read it via the directory branch of the read action (content is empty and only a revision is returned)
- Reduce the file size below 8 MiB and retry the read
- Replace the non-regular file (fifo/socket/device) with a real .md file
Defensive patterns
Strategy: validation
Validate before calling
const st = fs.lstatSync(absPath);
if (!st.isFile() || st.size > 8 * 1024 * 1024) {
throw new Error('not a regular file or over 8 MiB — refuse to read as template');
} Try / catch
try {
const r = await manageTemplateFiles({ action: 'read', path: p });
} catch (e) {
if (String(e.message).includes('invalid template source file')) {
const isDir = await manageTemplateFiles({ action: 'list' }).then(l => l.find(x => x.path === p)?.isDir);
if (isDir) { /* handle directory branch: content is empty, revision only */ }
}
} Prevention
- Check the list result's isDir flag before issuing a read
- Never place fifos/sockets/symlinks inside data/templates/
- Enforce the 8 MiB cap client-side before reading
When it happens
Trigger: ManageTemplateFiles with action="read" where request.Path exists but is not a regular file (e.g. a directory handled before the directory branch, a fifo/socket created by another process), or a regular .md file whose size exceeds maxTemplateSourceSize (8 MiB).
Common situations: A directory slipped past the .md-extension check because of casing tricks or the path resolves to something other than a normal file; a sync tool replaced the template with a special file; the template grew past 8 MiB from pasted content.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- invalid custom emoji image
- path is required
- value exceeds %d bytes
- JSON node count exceeds %d
- attribute view [%s] has no available visible view
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/2c2f02993db84ab2.
Report an issue: GitHub.