flipped-aurora/gin-vue-admin · error
%s已存在
Error message
%s已存在
What it means
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.
Source
Thrown at server/service/system/sys_skills.go:573
func (s *SkillsService) createMarkdownFile(tool, skill, subDir, fileName, defaultContent, label string) (string, string, error) {
if !isSafeName(skill) {
return "", "", errors.New("技能名称不合法")
}
cleanName, err := buildResourceFileName(fileName)
if err != nil {
return "", "", err
}
skillDir, err := s.ensureSkillDir(tool, skill)
if err != nil {
return "", "", err
}
filePath := filepath.Join(skillDir, subDir, cleanName)
if _, err := os.Stat(filePath); err == nil {
if label == "" {
label = "文件"
}
return "", "", fmt.Errorf("%s已存在", label)
}
if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
return "", "", err
}
content := defaultContent
if err := os.WriteFile(filePath, []byte(content), 0644); err != nil {
return "", "", err
}
return cleanName, content, nil
}
func (s *SkillsService) readSkillFile(tool, skill, subDir, fileName string) (string, error) {
if !isSafeName(skill) {
return "", errors.New("技能名称不合法")
}
if !isSafeFileName(fileName) {
return "", errors.New("文件名不合法")
}View on GitHub (pinned to 3136500ef3)
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
Example fix
// before
svc.CreateTemplate(skillName, "README") // 文件已存在
// after
if _, err := os.Stat(filepath.Join(skillsDir, skillName, "README.md")); err == nil {
svc.CreateTemplate(skillName, "README-2")
} else {
svc.CreateTemplate(skillName, "README")
} Defensive patterns
Strategy: validation
Validate before calling
// Go: check existence before calling create/create APIs
path := filepath.Join(skillDir, subDir, cleanName)
if _, err := os.Stat(path); err == nil {
// already exists: choose another name or delete first
} Type guard
// Go: name-existence guard
func fileExists(path string) bool {
_, err := os.Stat(path)
return err == nil
} Try / catch
name, _, err := svc.CreateTemplate(skillName, candidate)
if err != nil && strings.HasSuffix(err.Error(), "已存在") {
candidate = candidate + "-2"
name, _, err = svc.CreateTemplate(skillName, candidate)
} Prevention
- 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
When it happens
Trigger: Calling CreateResource, CreateReference, or CreateTemplate with a name that resolves (after cleaning + subDir) to a path that already exists inside the skill directory.
Common situations: 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.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31).
Data as JSON: /api/errors/d7f7c0325f9ec480.
Report an issue: GitHub.