siyuan-note/siyuan · error
invalid template source
Error message
invalid template source
What it means
writeTemplateSource is the single write path for template content, used by both create and replace. It first verifies the incoming content string is valid UTF-8; since Go strings can technically hold invalid UTF-8 bytes (e.g. from raw byte slices or decoded JSON with escapes), this rejects content that could not be stored as a proper text template. The write is then performed atomically via a same-directory temp file and rename.
Source
Thrown at kernel/model/template_manage.go:171
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)
if err != nil {
return err
}
_, err = file.WriteString(content)
if err == nil {
err = file.Sync()
}
closeErr := file.Close()
if err != nil {
root.Remove(p)
return err
}
return closeErr
}
tmp := path.Join(path.Dir(p), ".template-"+ast.NewNodeID())View on GitHub (pinned to 8641553a1f)
Solutions
- Ensure the HTTP client sends the content as a UTF-8 JSON string (string escapes like \uXXXX are fine)
- Convert the source text to UTF-8 before writing, e.g. iconv or an encoding-aware reader in your script
- If writing from bytes in Go/Node, validate utf8.Valid(bytes) / Buffer.isUtf8(bytes) before embedding into the JSON payload
Example fix
// before (Go client)
content := string(rawGBKBytes)
req := TemplateFileRequest{Action: "write", Path: "t.md", Content: content}
// after
if !utf8.Valid(rawGBKBytes) { rawGBKBytes, _ = gbkToUTF8(rawGBKBytes) }
req := TemplateFileRequest{Action: "write", Path: "t.md", Content: string(rawGBKBytes)} Defensive patterns
Strategy: validation
Validate before calling
const bytes = Buffer.from(content, 'utf8');
if (!Buffer.isUtf8(bytes)) {
throw new Error('content is not valid UTF-8');
} Try / catch
try {
await manageTemplateFiles({ action: 'write', path: p, revision: rev, content });
} catch (e) {
if (String(e.message).includes('invalid template source')) {
// re-encode content from its source encoding to UTF-8 and retry
}
} Prevention
- Send template content as JSON strings over HTTP (never raw bytes in a text field)
- Convert legacy encodings (GBK, Shift-JIS) to UTF-8 before writing
- In Go clients, check utf8.ValidString before building the request
When it happens
Trigger: ManageTemplateFiles with action="write" where request.Content, after JSON decoding, contains invalid UTF-8 — typically when a client sends raw binary bytes or a string built from non-UTF-8 byte data instead of properly encoded text.
Common situations: A script POSTs file bytes read with the wrong encoding; a client library mangles multi-byte characters; an integration writes templates from a legacy-encoded source without converting first.
Related errors
- template source is not UTF-8
- path is required
- 344
- attribute view [%s] has no available visible view
- invalid content template path
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/d745700067edd7f1.
Report an issue: GitHub.