{"record":{"id":"efe35191ab3f8954","repo":"larksuite/cli","slug":"required-skill-q-declared-by-q-is-not-a-valid-sk","errorCode":null,"errorMessage":"required skill %q declared by %q is not a valid skill name","messagePattern":"required skill %q declared by %q is not a valid skill name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/skillpolicy/dependencies.go","lineNumber":81,"sourceCode":"\t}\n\n\tvar frontmatter struct {\n\t\tMetadata struct {\n\t\t\tRequires struct {\n\t\t\t\tSkills []string `yaml:\"skills\"`\n\t\t\t} `yaml:\"requires\"`\n\t\t} `yaml:\"metadata\"`\n\t}\n\tif err := yaml.Unmarshal([]byte(strings.Join(block, \"\\n\")), &frontmatter); err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot parse SKILL.md frontmatter: %w\", err)\n\t}\n\n\trequired := frontmatter.Metadata.Requires.Skills\n\tseen := make(map[string]struct{}, len(required))\n\tout := make([]string, 0, len(required))\n\tfor _, dependency := range required {\n\t\tif !isSkillName(dependency) {\n\t\t\treturn nil, fmt.Errorf(\"required skill %q declared by %q is not a valid skill name\", dependency, skillName)\n\t\t}\n\t\tif _, duplicate := seen[dependency]; duplicate {\n\t\t\tcontinue\n\t\t}\n\t\tseen[dependency] = struct{}{}\n\t\tout = append(out, dependency)\n\t}\n\treturn out, nil\n}\n\n// validateRequiredSkills checks the already-composed owner manifest. It must\n// run after Base -> Allow -> Remove -> Overlay so no validation branch can\n// accidentally disagree with the tree that list/read actually serves.\nfunc validateRequiredSkills(composed *overlayFS) error {\n\tif composed == nil {\n\t\treturn nil\n\t}\n\tnames := make([]string, 0, len(composed.owner))","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/skillpolicy/dependencies.go#L63-L99","documentation":"Each entry in metadata.requires.skills must pass isSkillName; parseRequiredSkills throws \"required skill %q declared by %q is not a valid skill name\" for entries violating the skill-name rules. This keeps dependency references resolvable and unambiguous within the composed skill tree.","triggerScenarios":"A skills list entry fails isSkillName — e.g. it contains a slash/path (\"skills/foo\"), uppercase letters, spaces, empty string, or other characters outside the allowed skill-name character set.","commonSituations":"Writing a filesystem path or URL instead of the skill name; casing mistakes like \"My-Skill\"; stray quotes, commas, or trailing whitespace inside YAML flow lists; referencing a skill by its display title rather than its name.","solutions":["Rename the dependency to a valid skill name (lowercase kebab-case, no slashes or spaces)","Match the dependency string exactly to the target skill directory's name","Trim stray whitespace/quotes from the list entries","Check the referenced skill's actual name via its SKILL.md or the skill registry"],"exampleFix":"// before\nskills: [deployment/Skill-A, My Skill]\n// after\nskills: [deployment-skill-a]","handlingStrategy":"validation","validationCode":"var validSkillName = regexp.MustCompile(`^[a-z0-9]+(-[a-z0-9]+)*$`)\nfor _, dep := range requiredSkills {\n    if !validSkillName.MatchString(dep) {\n        return fmt.Errorf(\"invalid required skill name %q; use lowercase kebab-case\", dep)\n    }\n}","typeGuard":null,"tryCatchPattern":"if _, err := parseRequiredSkills(name, data); err != nil {\n    if strings.Contains(err.Error(), \"is not a valid skill name\") {\n        return fmt.Errorf(\"skill %s: rename dependencies to valid skill names (lowercase, no slashes/spaces)\", name)\n    }\n    return err\n}","preventionTips":["Use lowercase kebab-case for skill names everywhere","Reference directory names, never paths, titles, or URLs","Trim whitespace and quotes in YAML lists","Add a lint that validates every requires.skills entry against the naming rules"],"tags":["skillpolicy","naming","validation","frontmatter"],"backgroundTag":"invalid-skill-name","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}