{"record":{"id":"5f105c492ddb74d0","repo":"Tencent/WeKnora","slug":"skill-name-is-d-characters-maximum-is-d","errorCode":null,"errorMessage":"skill name is %d characters; maximum is %d","messagePattern":"skill name is (.+?) characters; maximum is (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/agent/skills/skill.go","lineNumber":88,"sourceCode":"\tBasePath    string // Path to skill directory for later loading\n}\n\n// SkillFile represents an additional file within a skill directory (Level 3)\ntype SkillFile struct {\n\tName     string // Filename (e.g., \"FORMS.md\", \"scripts/validate.py\")\n\tPath     string // Absolute path to the file\n\tContent  string // File content\n\tIsScript bool   // Whether this is an executable script\n}\n\n// Validate checks if the skill metadata is valid according to Claude's specification\nfunc (s *Skill) Validate() error {\n\t// Validate name\n\tif s.Name == \"\" {\n\t\treturn errors.New(\"skill name is required\")\n\t}\n\tif n := utf8.RuneCountInString(s.Name); n > MaxNameLength {\n\t\treturn fmt.Errorf(\"skill name is %d characters; maximum is %d\", n, MaxNameLength)\n\t}\n\tif !namePattern.MatchString(s.Name) {\n\t\treturn errors.New(\"skill name must contain only letters, numbers, hyphens, and underscores\")\n\t}\n\tfor _, reserved := range reservedWords {\n\t\tif strings.Contains(s.Name, reserved) {\n\t\t\treturn fmt.Errorf(\"skill name cannot contain reserved word: %s\", reserved)\n\t\t}\n\t}\n\tif xmlTagPattern.MatchString(s.Name) {\n\t\treturn errors.New(\"skill name cannot contain XML tags\")\n\t}\n\n\t// Validate description\n\tif s.Description == \"\" {\n\t\treturn errors.New(\"skill description is required\")\n\t}\n\tif n := utf8.RuneCountInString(s.Description); n > MaxDescriptionLength {","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/agent/skills/skill.go#L70-L106","documentation":"Skill.Validate enforces the Claude skill-spec limit on name length: a name longer than MaxNameLength runes is rejected. Length is measured in runes (not bytes), so non-ASCII names are counted fairly. This fires during skill parsing/installation (ParseSkillFile) before the skill can be registered.","triggerScenarios":"Installing/parsing a SKILL.md whose frontmatter name exceeds MaxNameLength characters — typically long auto-generated names, titles used verbatim as names, or verbose Chinese/multi-word names.","commonSituations":"Third-party skills with display titles in 'name'; generated skill names embedding long task descriptions; archives created by external tools without length validation.","solutions":["Shorten the 'name' field in SKILL.md frontmatter to MaxNameLength characters or fewer (use a kebab-case id, put the long title in 'description')","Rely on applyInstallName to derive a valid install id from slug/title when available","Regenerate the skill archive with a corrected frontmatter name","Check MaxNameLength in the skills package and validate the name before packaging"],"exampleFix":"# before\n---\nname: very-long-auto-generated-skill-name-exceeding-the-limit-value\n---\n# after\n---\nname: doc-converter\n---","handlingStrategy":"validation","validationCode":"if n := utf8.RuneCountInString(name); n > skills.MaxNameLength {\n    return fmt.Errorf(\"name %d runes exceeds max %d\", n, skills.MaxNameLength)\n}\nif err := skill.Validate(); err != nil { return err }","typeGuard":"func validSkillName(name string) bool {\n    return utf8.RuneCountInString(name) <= skills.MaxNameLength\n}","tryCatchPattern":"if err := skill.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"maximum is\") {\n        skill.Name = truncateToRunes(skill.Name, skills.MaxNameLength)\n        return skill.Validate()\n    }\n    return err\n}","preventionTips":["Derive 'name' from a short kebab-case id, not the display title","Validate SKILL.md frontmatter at packaging time, before distribution","Run skill.Validate() in CI for skill repositories","Count runes, not bytes, when pre-checking non-ASCII names"],"tags":["go","validation","skill-metadata","frontmatter"],"backgroundTag":"skill-name-too-long","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}