{"record":{"id":"172b6c0adb710d11","repo":"siyuan-note/siyuan","slug":"template-source-is-too-large-172b6c","errorCode":null,"errorMessage":"template source is too large","messagePattern":"template source is too large","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/template_manage.go","lineNumber":141,"sourceCode":"\th := sha256.New()\n\tif info.IsDir() {\n\t\terr = fs.WalkDir(root.FS(), p, func(name string, entry fs.DirEntry, walkErr error) error {\n\t\t\tif walkErr != nil {\n\t\t\t\treturn walkErr\n\t\t\t}\n\t\t\tstat, statErr := entry.Info()\n\t\t\tif statErr != nil {\n\t\t\t\treturn statErr\n\t\t\t}\n\t\t\tif stat.Mode()&os.ModeSymlink != 0 {\n\t\t\t\treturn errors.New(\"template directory contains a symbolic link\")\n\t\t\t}\n\t\t\tfmt.Fprintf(h, \"%s\\x00%d\\x00%d\\x00%d\\n\", name, stat.Size(), stat.ModTime().UnixNano(), stat.Mode())\n\t\t\treturn nil\n\t\t})\n\t} else {\n\t\tif info.Size() > maxTemplateSourceSize {\n\t\t\treturn \"\", errors.New(\"template source is too large\")\n\t\t}\n\t\tvar content []byte\n\t\tcontent, err = root.ReadFile(p)\n\t\th.Write(content)\n\t}\n\treturn fmt.Sprintf(\"%x\", h.Sum(nil)), err\n}\n\nfunc readTemplateSource(root *os.Root, p string) (string, error) {\n\tinfo, err := root.Stat(p)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tif !info.Mode().IsRegular() || info.Size() > maxTemplateSourceSize {\n\t\treturn \"\", errors.New(\"invalid template source file\")\n\t}\n\tcontent, err := root.ReadFile(p)\n\tif err != nil {","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/template_manage.go#L123-L159","documentation":"templateFileRevision computes a SHA-256 revision fingerprint of a template file or directory. For a regular file it reads the whole content into memory to hash it, but first rejects any file larger than maxTemplateSourceSize (8 MiB) so a single template cannot force the kernel to buffer an unbounded amount of data. The error means the template file exceeds the 8 MiB size cap, so no revision (and hence no save/move/delete that requires optimistic concurrency) can be computed for it.","triggerScenarios":"Calling ManageTemplateFiles with any action other than 'list'/'mkdir' on an existing non-directory template whose on-disk size is > 8388608 bytes: the request first reaches templateFileRevision via the revision check (template_manage.go:269), so even 'read' on an oversized file fails here before readTemplateSource runs.","commonSituations":"A user pasted a huge log/dataset into a template and saved it externally; a file was dropped into data/templates/ by another tool or sync service and happens to be over 8 MiB; a .md was renamed from an export that embedded large base64 images.","solutions":["Shrink or split the template file so it is under 8 MiB, e.g. move large assets out of the markdown into the assets folder and reference them","If the file is not really a template, move it out of data/templates/ so it is not managed","If the file legitimately needs to be large, recreate it as a template package (directory with template.json) — directory revisions only hash metadata, not content"],"exampleFix":"// oversized single template\ndata/templates/big-notes.md        (12 MB)\n// after\n data/templates/big-notes/template.json\ndata/templates/big-notes/big-notes.md  (still read-capped, but revision hashing no longer buffers file content)","handlingStrategy":"validation","validationCode":"const info = fs.statSync(path.join(dataDir, 'templates', p));\nif (!info.isDirectory() && info.size > 8 * 1024 * 1024) {\n  throw new Error('template exceeds 8 MiB cap; shrink or move it out of templates/');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await manageTemplateFiles({ action: 'read', path: p, revision: rev });\n} catch (e) {\n  if (String(e.message).includes('template source is too large')) {\n    // surface a 'file too large to manage' message and offer to move the file out of templates/\n  }\n}","preventionTips":["Keep templates as reusable snippets, not full data dumps","Store large assets under assets/ and reference them instead of embedding base64","Periodically audit data/templates/ for files synced in from other tools"],"tags":["file-size","template","validation","limit"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}