{"record":{"id":"7fe1b935140fae86","repo":"larksuite/cli","slug":"skill-md-frontmatter-is-not-closed","errorCode":null,"errorMessage":"SKILL.md frontmatter is not closed","messagePattern":"SKILL\\.md frontmatter is not closed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/skillpolicy/dependencies.go","lineNumber":62,"sourceCode":"\t// A UTF-8 text file may begin with one BOM. Normalize it before checking\n\t// the delimiter so BOM-prefixed dependency metadata cannot be skipped.\n\tcontent := strings.TrimPrefix(string(skillMD), \"\\uFEFF\")\n\tlines := strings.Split(content, \"\\n\")\n\tif strings.TrimRight(lines[0], \"\\r\") != \"---\" {\n\t\treturn nil, nil\n\t}\n\n\tblock := make([]string, 0, len(lines))\n\tclosed := false\n\tfor _, line := range lines[1:] {\n\t\tif strings.TrimRight(line, \"\\r\") == \"---\" {\n\t\t\tclosed = true\n\t\t\tbreak\n\t\t}\n\t\tblock = append(block, line)\n\t}\n\tif !closed {\n\t\treturn nil, fmt.Errorf(\"SKILL.md frontmatter is not closed\")\n\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) {","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/skillpolicy/dependencies.go#L44-L80","documentation":"parseRequiredSkills scans the leading `---` delimited YAML frontmatter of SKILL.md and throws \"SKILL.md frontmatter is not closed\" when the opening `---` block never terminates. The library refuses to guess which lines are frontmatter, so an unterminated block makes the skill's dependency declaration unparsable.","triggerScenarios":"SKILL.md starts with `---` but no matching closing `---` line appears before the scan ends — e.g. the closing delimiter was deleted, indented, or written as `----`/```---` with extra characters.","commonSituations":"Hand-editing SKILL.md and accidentally removing the second `---`; copy-pasting frontmatter that lost its trailing delimiter; a templating step truncating the file; writing the delimiter with leading whitespace so it is not recognized.","solutions":["Add the closing `---` line immediately after the frontmatter keys, at column 0","Remove any leading whitespace before both `---` delimiters","Run the skill-format check (node scripts/skill-format-check/index.js) to catch malformed frontmatter","Validate the SKILL.md against a known-good skill file's structure"],"exampleFix":"// before\n---\nmetadata:\n  requires:\n    skills: [foo]\n   (no closing delimiter)\n// after\n---\nmetadata:\n  requires:\n    skills: [foo]\n---","handlingStrategy":"validation","validationCode":"func frontmatterClosed(data []byte) bool {\n    lines := strings.Split(string(data), \"\\n\")\n    if len(lines) == 0 || strings.TrimSpace(lines[0]) != \"---\" { return false }\n    for _, l := range lines[1:] {\n        if strings.TrimSpace(l) == \"---\" { return true }\n    }\n    return false\n}\n// if !frontmatterClosed(skillMD) { fix the file }","typeGuard":null,"tryCatchPattern":"if _, err := parseRequiredSkills(name, data); err != nil {\n    if strings.Contains(err.Error(), \"frontmatter is not closed\") {\n        return fmt.Errorf(\"skill %s: add the closing '---' line after the frontmatter block\", name)\n    }\n    return err\n}","preventionTips":["Always close frontmatter with `---` at column 0","Run node scripts/skill-format-check/index.js on skill files in CI","Avoid hand-editing SKILL.md frontmatter without re-validating","Lint for indented or malformed --- delimiters"],"tags":["skillpolicy","frontmatter","yaml","skill-format"],"backgroundTag":"unclosed-frontmatter","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"}