siyuan-note/siyuan · error

renderDocRef path target must be a document path

Error message

renderDocRef path target must be a document path

What it means

In renderDocRef "path" mode, the target must be a string containing the human-readable path of a document in the current doc tree. If the value is not a string, the call fails with "renderDocRef path target must be a document path". Note the check happens before path cleaning and matching, so any non-string type triggers it immediately.

Source

Thrown at kernel/model/template_doc_tree.go:263

	switch mode {
	case "children":
		id, ok := value.(string)
		if !ok {
			return nil, errors.New("renderDocRef children target must be a document ID")
		}
		if collector.rootID == id {
			return collector.nodes, nil
		}
		for _, node := range flattenTemplateDocTreeNodes0(collector.nodes) {
			if node.ID == id {
				return node.Children, nil
			}
		}
		return []*TemplateDocTreeNode{}, nil
	case "path":
		hPath, ok := value.(string)
		if !ok {
			return "", errors.New("renderDocRef path target must be a document path")
		}
		requestedPath := path.Clean(hPath)
		for _, node := range flattenTemplateDocTreeNodes0(collector.nodes) {
			relativePath := strings.TrimPrefix(node.HPath, collector.rootHPath)
			if node.HPath == requestedPath || relativePath == requestedPath {
				return fmt.Sprintf("((%s %q))", node.RootID, node.HPath), nil
			}
		}
		return "", nil
	default:
		return nil, fmt.Errorf("unsupported renderDocRef query mode [%s]", mode)
	}
}

func flattenTemplateDocTreeNodes0(nodes []*TemplateDocTreeNode) (ret []*TemplateDocTreeNode) {
	for _, node := range nodes {
		ret = append(ret, node)
		ret = append(ret, flattenTemplateDocTreeNodes0(node.Children)...)

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Pass a quoted path string: renderDocRef("path", "/Parent/Child").
  2. Ensure interpolated variables produce strings (apply string formatting).
  3. Use the node's hPath value, not the node object itself.

Example fix

// before
renderDocRef("path", ."/Docs/" . $n)  // $n is a number, still a string — but raw node objects are not
// after
renderDocRef("path", "/Docs/Chapter 1")
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof target !== "string") throw new Error("path target must be a string hPath");

Type guard

const isHPath = (v) => typeof v === "string" && v.startsWith("/");

Try / catch

try {
  const ref = renderDocRef("path", target);
} catch (e) {
  if (String(e).includes("must be a document path")) {
    // convert node objects/ids to their hPath string
  }
}

Prevention

When it happens

Trigger: Calling renderDocRef("path", 42), renderDocRef("path", nil), or passing a list/object where a path string like "/Parent/Child" is expected.

Common situations: Template variable interpolation that yields a non-string; passing node data structures instead of their hPath string; typos where the ID was given to the path mode (that returns empty, but a wrong type errors).

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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