{"record":{"id":"3f44c289ed6bde45","repo":"siyuan-note/siyuan","slug":"unsupported-template-operation","errorCode":null,"errorMessage":"unsupported template operation","messagePattern":"unsupported template operation","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/template_manage.go","lineNumber":321,"sourceCode":"\t\t\treturn nil, errors.New(\"template source must use the .md extension\")\n\t\t}\n\t\tif _, err = root.Stat(request.Target); !errors.Is(err, os.ErrNotExist) {\n\t\t\treturn nil, errors.New(\"template destination already exists or is inaccessible\")\n\t\t}\n\t\treturn nil, root.Rename(request.Path, request.Target)\n\tcase \"remove\":\n\t\t// 将整个目录连同包资源移入隐藏恢复目录，保留误删后的恢复材料。\n\t\ttrash := \".trash/\" + ast.NewNodeID()\n\t\tif err = root.MkdirAll(trash, 0700); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\ttarget := path.Join(trash, path.Base(request.Path))\n\t\tif err = root.Rename(request.Path, target); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn map[string]string{\"recoveryPath\": target}, nil\n\tdefault:\n\t\treturn nil, errors.New(\"unsupported template operation\")\n\t}\n}\n","sourceCodeStart":303,"sourceCodeEnd":324,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/template_manage.go#L303-L324","documentation":"ManageTemplateFiles supports a fixed set of actions (list, create, read, write, move, remove, etc.); any other action value falls through to the switch default and returns this error. It is a simple operation-enum guard so unknown or misspelled actions fail fast instead of silently doing nothing.","triggerScenarios":"Calling the kernel's manageTemplateFiles API (HTTP /api/template/manageTemplateFiles) with a request.Action that is not one of the supported verbs — typo (e.g. 'delete' instead of 'remove'), missing action, or a plugin using an action from a newer/older API version.","commonSituations":"Plugin code written against a different API version using an action that no longer exists; hand-crafted HTTP calls with 'delete'/'rm'/'copy' guesses; empty action field because the payload was mis-built.","solutions":["Use one of the supported action strings exactly (e.g. \"list\", \"create\", \"read\", \"write\", \"move\", \"remove\")","If you meant deletion, use action=\"remove\" instead of \"delete\"","Check the API definition for TemplateFileRequest.Action in the current kernel version to see the valid enum"],"exampleFix":"// before\n{ \"action\": \"delete\", \"path\": \"/old.md\" }\n// after\n{ \"action\": \"remove\", \"path\": \"/old.md\" }","handlingStrategy":"validation","validationCode":"const ALLOWED = ['list','create','read','write','move','remove'];\nif (!ALLOWED.includes(request.action)) {\n  throw new Error('unsupported action: ' + request.action);\n}","typeGuard":"const isValidAction = (a) =>\n  typeof a === 'string' && ['list','create','read','write','move','remove'].includes(a);","tryCatchPattern":"try {\n  return await fetchPost('/api/template/manageTemplateFiles', request);\n} catch (e) {\n  if (String(e.message).includes('unsupported template operation')) {\n    console.error('Bad action, valid values: list|create|read|write|move|remove', request.action);\n  }\n  throw e;\n}","preventionTips":["Copy action strings from the API definition, never retype them","Centralize API calls in a wrapper that validates the action enum once","Check API changelogs when upgrading between kernel versions"],"tags":["api","templates","enum"],"backgroundTag":"invalid-enum-value","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"}