{"record":{"id":"022356b6b4e5ad52","repo":"siyuan-note/siyuan","slug":"renderdocref-path-target-must-be-a-document-path","errorCode":null,"errorMessage":"renderDocRef path target must be a document path","messagePattern":"renderDocRef path target must be a document path","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/template_doc_tree.go","lineNumber":263,"sourceCode":"\tswitch mode {\n\tcase \"children\":\n\t\tid, ok := value.(string)\n\t\tif !ok {\n\t\t\treturn nil, errors.New(\"renderDocRef children target must be a document ID\")\n\t\t}\n\t\tif collector.rootID == id {\n\t\t\treturn collector.nodes, nil\n\t\t}\n\t\tfor _, node := range flattenTemplateDocTreeNodes0(collector.nodes) {\n\t\t\tif node.ID == id {\n\t\t\t\treturn node.Children, nil\n\t\t\t}\n\t\t}\n\t\treturn []*TemplateDocTreeNode{}, nil\n\tcase \"path\":\n\t\thPath, ok := value.(string)\n\t\tif !ok {\n\t\t\treturn \"\", errors.New(\"renderDocRef path target must be a document path\")\n\t\t}\n\t\trequestedPath := path.Clean(hPath)\n\t\tfor _, node := range flattenTemplateDocTreeNodes0(collector.nodes) {\n\t\t\trelativePath := strings.TrimPrefix(node.HPath, collector.rootHPath)\n\t\t\tif node.HPath == requestedPath || relativePath == requestedPath {\n\t\t\t\treturn fmt.Sprintf(\"((%s %q))\", node.RootID, node.HPath), nil\n\t\t\t}\n\t\t}\n\t\treturn \"\", nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unsupported renderDocRef query mode [%s]\", mode)\n\t}\n}\n\nfunc flattenTemplateDocTreeNodes0(nodes []*TemplateDocTreeNode) (ret []*TemplateDocTreeNode) {\n\tfor _, node := range nodes {\n\t\tret = append(ret, node)\n\t\tret = append(ret, flattenTemplateDocTreeNodes0(node.Children)...)","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/template_doc_tree.go#L245-L281","documentation":"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.","triggerScenarios":"Calling renderDocRef(\"path\", 42), renderDocRef(\"path\", nil), or passing a list/object where a path string like \"/Parent/Child\" is expected.","commonSituations":"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).","solutions":["Pass a quoted path string: renderDocRef(\"path\", \"/Parent/Child\").","Ensure interpolated variables produce strings (apply string formatting).","Use the node's hPath value, not the node object itself."],"exampleFix":"// before\nrenderDocRef(\"path\", .\"/Docs/\" . $n)  // $n is a number, still a string — but raw node objects are not\n// after\nrenderDocRef(\"path\", \"/Docs/Chapter 1\")","handlingStrategy":"type-guard","validationCode":"if (typeof target !== \"string\") throw new Error(\"path target must be a string hPath\");","typeGuard":"const isHPath = (v) => typeof v === \"string\" && v.startsWith(\"/\");","tryCatchPattern":"try {\n  const ref = renderDocRef(\"path\", target);\n} catch (e) {\n  if (String(e).includes(\"must be a document path\")) {\n    // convert node objects/ids to their hPath string\n  }\n}","preventionTips":["Pass the node's hPath string, never the node object","Validate interpolation results are strings before passing","Document that path mode expects a slash-prefixed path string"],"tags":["template","type-mismatch","argument"],"backgroundTag":"type-mismatch","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}