{"record":{"id":"74bd02728cd81631","repo":"siyuan-note/siyuan","slug":"install-skill-s-failed-s","errorCode":null,"errorMessage":"install skill %s failed: %s","messagePattern":"install skill (.+?) failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/skill.go","lineNumber":532,"sourceCode":"\t\t\t\tcontinue\n\t\t\t}\n\t\t\tname = filepath.Base(rel)\n\t\t}\n\t\tif verr := validateSkillName(name); verr != nil {\n\t\t\tlogging.LogWarnf(\"skip invalid skill name [%s]: %s\", name, verr)\n\t\t\tcontinue\n\t\t}\n\n\t\tdestDir := filepath.Join(SkillsDir(), name)\n\t\tif err := os.MkdirAll(SkillsDir(), 0755); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\t// 覆盖式安装：先清旧目录\n\t\tif gulu.File.IsExist(destDir) {\n\t\t\tos.RemoveAll(destDir)\n\t\t}\n\t\tif err := filelock.Copy(srcDir, destDir); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"install skill %s failed: %s\", name, err)\n\t\t}\n\t\tresult.Names = append(result.Names, name)\n\t\tdesc := fm[\"description\"]\n\t\tif desc == \"\" {\n\t\t\tdesc = firstLine(body)\n\t\t}\n\t\tresult.Descriptions = append(result.Descriptions, desc)\n\t}\n\tif len(result.Names) == 0 {\n\t\treturn nil, errors.New(\"no valid skill installed\")\n\t}\n\treturn result, nil\n}\n\n// installFromSingleSkillMD 把单个 SKILL.md 文本内容落地为一个 skill\nfunc installFromSingleSkillMD(data []byte) (*InstallSkillResult, error) {\n\tcontent := string(data)\n\tfm, body := parseSkillFrontmatter(content)","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/util/skill.go#L514-L550","documentation":"Thrown by installSkillDirs when filelock.Copy fails while copying a discovered skill directory from the temp unzip area into SkillsDir(). Earlier steps (reading SKILL.md, validating the name, removing any pre-existing dest) have already succeeded.","triggerScenarios":"A permission error writing into SkillsDir(); a path-length or filename encoding issue on the destination filesystem; the source directory contains a file filelock cannot copy (special files, symlinks it rejects); disk full.","commonSituations":"Restrictive filesystem permissions on data/storage/ai/agent/skills; antivirus or sync software locking files on Windows; an exotic file in the skill archive; insufficient disk space.","solutions":["Verify write permissions and free space under the workspace data/storage/ai/agent/skills directory.","Retry after disabling any sync client (OneDrive/Dropbox) or AV that may lock the directory on Windows.","Inspect the skill archive for special files or symlinks and remove them.","Re-run install after freeing disk space."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"res, err := util.InstallSkill(src)\nif err != nil && strings.HasPrefix(err.Error(), \"install skill \") {\n    // inspect destination permissions and free space, then retry once\n    ensureWritable(util.SkillsDir())\n}","preventionTips":["Keep the workspace data directory writable and on a volume with free space.","Pause sync clients (OneDrive/Dropbox) and AV scanners during install on Windows.","Avoid special files and absolute symlinks inside skill archives."],"tags":["skill-management","filesystem","io"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}