siyuan-note/siyuan · error
invalid skill name: %s
Error message
invalid skill name: %s
What it means
Thrown by validateSkillName (kernel/util/skill.go:108) when the supplied skill name is the empty string, ".", or "..". It is the first of three guards in validateSkillName and blocks trivially empty or self/parent-referential names before any filesystem operation. ReadSkill/SaveSkill/RemoveSkill/RenameSkill all run it first.
Source
Thrown at kernel/util/skill.go:108
b, err := filelock.ReadFile(skillMdPath)
if err != nil {
continue
}
fm, body := parseSkillFrontmatter(string(b))
skillName := fm["name"]
if skillName == "" {
skillName = e.Name()
}
if strings.EqualFold(skillName, name) || strings.EqualFold(e.Name(), name) {
return body
}
}
return ""
}
func validateSkillName(name string) error {
if name == "" || name == "." || name == ".." {
return fmt.Errorf("invalid skill name: %s", name)
}
if strings.ContainsAny(name, `/\`) {
return fmt.Errorf("invalid skill name: %s", name)
}
dir := SkillsDir()
abs := filepath.Join(dir, name)
if !gulu.File.IsSubPath(dir, abs) {
return fmt.Errorf("invalid skill name: %s", name)
}
return nil
}
func ReadSkill(name string) (string, error) {
if err := validateSkillName(name); err != nil {
return "", err
}
skillMdPath := filepath.Join(SkillsDir(), name, "SKILL.md")
b, err := filelock.ReadFile(skillMdPath)View on GitHub (pinned to 251596fc0d)
Solutions
- Validate the name on the caller side before invoking the skill API (non-empty, not "." or "..").
- Disable the submit button until a non-empty name is entered in the UI.
- Audit the request payload to confirm the name field is being serialized.
Example fix
// before
err := util.SaveSkill(req.Name, req.Content)
// after
name := strings.TrimSpace(req.Name)
if name == "" || name == "." || name == ".." {
return errors.New("skill name must be a non-empty, non-traversal name")
}
err := util.SaveSkill(name, req.Content) Defensive patterns
Strategy: validation
Validate before calling
name := strings.TrimSpace(req.Name)
if name == "" || name == "." || name == ".." {
return errors.New("skill name must be a non-empty value other than '.' or '..'")
} Try / catch
if err := util.ReadSkill(name); err != nil {
if strings.HasPrefix(err.Error(), "invalid skill name") {
// input-validation failure; surface to user, do not retry unchanged
return userFacingValidationError{err}
}
return err
} Prevention
- Always TrimSpace and reject empty/./.. on the caller side before the skill API.
- Disable submit in the UI until a non-trivial name is entered.
- Add a unit test that the API rejects zero-value names.
When it happens
Trigger: Calling ReadSkill(""), SaveSkill(".", ...), or RemoveSkill("..") — typically a caller bug that passed an unset/zero-value name, or a UI form that submitted before a name was entered.
Common situations: Frontend sends a skill API request without filling the name field; a script iterates a list and forwards an empty entry; a rename operation passed an empty newName.
Related errors
- path escapes templates dir: %s
- invalid package name
- image prompt is required
- skill not found: %s
- image attachment request limit exceeded: at most %d images a
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/5e257eff0e2e4dce.
Report an issue: GitHub.