siyuan-note/siyuan · error

template output exceeds %d bytes

Error message

template output exceeds %d bytes

What it means

After executing a createDocTree template, the kernel checks the rendered output size: if the template used createDocTree (collector.nodes non-empty) and the rendered buffer exceeds maxTemplateDocTreeOutputSize, rendering aborts with this error. The limit protects the kernel from a runaway template that would create a huge document tree.

Source

Thrown at kernel/model/template.go:830

	tpl, err := goTpl.Funcs(tplFuncMap).Parse(gulu.Str.FromBytes(md))
	if err != nil {
		err = fmt.Errorf(Conf.Language(44), err.Error())
		return
	}
	if collector.enabled && templateUsesFunction(tpl, "createDocTree") {
		if err = validateTemplateCallGraph(tpl, tpl.Name()); nil != err {
			return
		}
	}

	buf := &bytes.Buffer{}
	buf.Grow(4096)
	if err = tpl.Execute(buf, dataModel); err != nil {
		err = fmt.Errorf(Conf.Language(44), err.Error())
		return
	}
	if 0 < len(collector.nodes) && maxTemplateDocTreeOutputSize < buf.Len() {
		err = fmt.Errorf("template output exceeds %d bytes", maxTemplateDocTreeOutputSize)
		return
	}
	collector.totalOutput = buf.Len()
	md = buf.Bytes()
	tree, err = parseTemplateKTree(md)
	if err != nil {
		logging.LogErrorf("parse template [%s] failed: %s", p, err)
		return
	}
	tree.Box = sourceTree.Box
	if 0 < len(collector.nodes) {
		if err = collector.validateLocations(); nil != err {
			return
		}
		if templateTreeContainsAttributeView(tree) {
			err = errors.New("database blocks are not supported by createDocTree templates")
			return
		}

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Reduce the output size of the template: narrow queries with LIMIT or filters so fewer documents/blocks are generated.
  2. Split the template into several smaller templates run in separate steps.
  3. If legitimately needed, raise maxTemplateDocTreeOutputSize in kernel/model/template.go and rebuild the kernel (self-hosted only).

Example fix

// before (template markdown)
.action{$docs := queryBlocks "SELECT * FROM blocks"}
.action{range $docs}.action{createDocTree ...}.action{end}
// after
.action{$docs := queryBlocks "SELECT * FROM blocks WHERE type = 'd' LIMIT 50"}
.action{range $docs}.action{createDocTree ...}.action{end}
Defensive patterns

Strategy: validation

Validate before calling

// Estimate rendered size before invoking the render API
const maxTemplateDocTreeOutputSize = 10 * 1024 * 1024 // keep in sync with kernel
if len(strings.ReplaceAll(md, ".action{", "")) > maxTemplateDocTreeOutputSize { return errors.New("template too large") }
// Better: bound query results in the template itself (LIMIT clause)

Try / catch

if err := renderTemplateWithMode(p, mode); err != nil {
    if strings.Contains(err.Error(), "template output exceeds") {
        return fmt.Errorf("narrow the createDocTree queries in %s and retry", p)
    }
    return err
}

Prevention

When it happens

Trigger: Calling RenderTemplateWithMode or PreviewTemplateSource with a template that uses .action{createDocTree ...} and whose expanded output (loops over large query results, repeated document definitions) exceeds the configured byte limit.

Common situations: A createDocTree template looping over a query returning thousands of blocks; recursively generating deep document trees; large embedded content repeated for every generated document.

Understand the failure class

Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/84c1a9d241823068. Report an issue: GitHub.