{"record":{"id":"06ea7772a6da8042","repo":"siyuan-note/siyuan","slug":"path-is-required-06ea77","errorCode":null,"errorMessage":"path is required","messagePattern":"path is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/mcp/tools/template.go","lineNumber":92,"sourceCode":"func templateSearch(args map[string]any) (CallToolResult, error) {\n\tkeyword, _ := args[\"keyword\"].(string)\n\tresults := model.SearchTemplate(keyword)\n\tif len(results) == 0 {\n\t\treturn CallToolResult{Content: []ContentItem{{Type: \"text\", Text: \"no templates found\"}}}, nil\n\t}\n\n\tvar sb strings.Builder\n\tsb.WriteString(fmt.Sprintf(\"Templates (%d):\\n\\n\", len(results)))\n\tfor _, r := range results {\n\t\tsb.WriteString(fmt.Sprintf(\"- %s\\n\", r.Content))\n\t\tsb.WriteString(fmt.Sprintf(\"  path: %s\\n\", r.Path))\n\t}\n\treturn CallToolResult{Content: []ContentItem{{Type: \"text\", Text: sb.String()}}}, nil\n}\n\nfunc resolveTemplatePath(p string) (string, error) {\n\tif p == \"\" {\n\t\treturn \"\", fmt.Errorf(\"path is required\")\n\t}\n\tabs := p\n\tif !filepath.IsAbs(abs) {\n\t\tabs = filepath.Join(util.DataDir, \"templates\", p)\n\t}\n\tabs = filepath.Clean(abs)\n\ttemplatesBase := filepath.Clean(filepath.Join(util.DataDir, \"templates\"))\n\trel, err := filepath.Rel(templatesBase, abs)\n\tif err != nil || strings.HasPrefix(rel, \"..\") || rel == \"..\" {\n\t\treturn \"\", fmt.Errorf(\"path escapes templates dir: %s\", p)\n\t}\n\treturn abs, nil\n}\n\nfunc templateGet(args map[string]any) (CallToolResult, error) {\n\tp, _ := args[\"path\"].(string)\n\tabs, err := resolveTemplatePath(p)\n\tif err != nil {","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/mcp/tools/template.go#L74-L110","documentation":"`resolveTemplatePath` requires a non-empty `path` argument; an empty string is rejected immediately because there is no default template to select. Every template tool operation (get, remove, render) needs the caller to name the target template file.","triggerScenarios":"Calling `templateGet`/`templateRemove`/`templateRender` (or any consumer of `resolveTemplatePath`) with `args[\"path\"]` missing or set to `\"\"`.","commonSituations":"The MCP client omitted the `path` field from the arguments object, or sent `path: \"\"`. A caller assumed a default template would be chosen.","solutions":["Provide a non-empty `path` value, relative (under `data/templates/`) or absolute, pointing at the template file.","If you need to discover available templates first, call the list-templates tool, then pass a returned `path`."],"exampleFix":"// before\n{\"path\": \"\"}\n// after\n{\"path\": \"daily.md\"}","handlingStrategy":"validation","validationCode":"// Require a non-empty path before invoking a template tool.\nif strings.TrimSpace(p) == \"\" {\n    return errors.New(\"path is required\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass a non-empty template path.","List templates first and reuse a returned path verbatim.","Validate required arguments client-side."],"tags":["mcp","template","input-validation","path"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}