{"record":{"id":"d7f7c0325f9ec480","repo":"flipped-aurora/gin-vue-admin","slug":"s-d7f7c0","errorCode":null,"errorMessage":"%s已存在","messagePattern":"%s已存在","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/service/system/sys_skills.go","lineNumber":573,"sourceCode":"\nfunc (s *SkillsService) createMarkdownFile(tool, skill, subDir, fileName, defaultContent, label string) (string, string, error) {\n\tif !isSafeName(skill) {\n\t\treturn \"\", \"\", errors.New(\"技能名称不合法\")\n\t}\n\tcleanName, err := buildResourceFileName(fileName)\n\tif err != nil {\n\t\treturn \"\", \"\", err\n\t}\n\tskillDir, err := s.ensureSkillDir(tool, skill)\n\tif err != nil {\n\t\treturn \"\", \"\", err\n\t}\n\tfilePath := filepath.Join(skillDir, subDir, cleanName)\n\tif _, err := os.Stat(filePath); err == nil {\n\t\tif label == \"\" {\n\t\t\tlabel = \"文件\"\n\t\t}\n\t\treturn \"\", \"\", fmt.Errorf(\"%s已存在\", label)\n\t}\n\tif err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {\n\t\treturn \"\", \"\", err\n\t}\n\tcontent := defaultContent\n\tif err := os.WriteFile(filePath, []byte(content), 0644); err != nil {\n\t\treturn \"\", \"\", err\n\t}\n\treturn cleanName, content, nil\n}\n\nfunc (s *SkillsService) readSkillFile(tool, skill, subDir, fileName string) (string, error) {\n\tif !isSafeName(skill) {\n\t\treturn \"\", errors.New(\"技能名称不合法\")\n\t}\n\tif !isSafeFileName(fileName) {\n\t\treturn \"\", errors.New(\"文件名不合法\")\n\t}","sourceCodeStart":555,"sourceCodeEnd":591,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/service/system/sys_skills.go#L555-L591","documentation":"createMarkdownFile returns this error when the target markdown file already exists at skillDir/subDir/cleanName. os.Stat succeeds (err == nil), meaning the path exists, so creation is refused with a message stating what kind of item ('文件' by default) already exists. It is a deliberate duplicate-name guard surfaced to callers CreateResource, CreateReference and CreateTemplate.","triggerScenarios":"Calling CreateResource, CreateReference, or CreateTemplate with a name that resolves (after cleaning + subDir) to a path that already exists inside the skill directory.","commonSituations":"User retries a creation after a prior successful call; two skill items share the same cleaned filename (name normalization collapses distinct inputs to the same path); leftover files from a manual edit or partial migration already occupy the path.","solutions":["Pick a different name for the resource/reference/template, or delete/rename the existing file first","Check the skill directory (skillDir/subDir) for the existing file and remove stale leftovers if intentional","Note that name cleaning may map different raw names to the same path — choose a name that stays distinct after cleaning"],"exampleFix":"// before\nsvc.CreateTemplate(skillName, \"README\") // 文件已存在\n// after\nif _, err := os.Stat(filepath.Join(skillsDir, skillName, \"README.md\")); err == nil {\n    svc.CreateTemplate(skillName, \"README-2\")\n} else {\n    svc.CreateTemplate(skillName, \"README\")\n}","handlingStrategy":"validation","validationCode":"// Go: check existence before calling create/create APIs\npath := filepath.Join(skillDir, subDir, cleanName)\nif _, err := os.Stat(path); err == nil {\n    // already exists: choose another name or delete first\n}","typeGuard":"// Go: name-existence guard\nfunc fileExists(path string) bool {\n    _, err := os.Stat(path)\n    return err == nil\n}","tryCatchPattern":"name, _, err := svc.CreateTemplate(skillName, candidate)\nif err != nil && strings.HasSuffix(err.Error(), \"已存在\") {\n    candidate = candidate + \"-2\"\n    name, _, err = svc.CreateTemplate(skillName, candidate)\n}","preventionTips":["Check os.Stat on the target path before creating","Adopt unique/timestamped naming for generated files","Remember name cleaning may collide distinct inputs into the same path","Periodically clean stale files from skill directories"],"tags":["filesystem","duplicate","go"],"backgroundTag":"file-already-exists","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}