{"record":{"id":"6d983ee005931ff6","repo":"alibaba/spring-ai-alibaba","slug":"skill-description-is-required","errorCode":null,"errorMessage":"Skill description is required","messagePattern":"Skill description is required","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/skills/SkillMetadata.java","lineNumber":169,"sourceCode":"\t\t\treturn this;\n\t\t}\n\n\t\tpublic Builder fullContent(String fullContent) {\n\t\t\tmetadata.fullContent = fullContent;\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic Builder allowedTools(List<String> allowedTools) {\n\t\t\tmetadata.allowedTools = allowedTools == null ? List.of() : List.copyOf(allowedTools);\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic SkillMetadata build() {\n\t\t\tif (metadata.name == null || metadata.name.isEmpty()) {\n\t\t\t\tthrow new IllegalStateException(\"Skill name is required\");\n\t\t\t}\n\t\t\tif (metadata.description == null || metadata.description.isEmpty()) {\n\t\t\t\tthrow new IllegalStateException(\"Skill description is required\");\n\t\t\t}\n\t\t\tif (metadata.skillPath == null || metadata.skillPath.isEmpty()) {\n\t\t\t\tthrow new IllegalStateException(\"Skill path is required\");\n\t\t\t}\n\t\t\tif (metadata.allowedTools == null) {\n\t\t\t\tmetadata.allowedTools = List.of();\n\t\t\t}\n\t\t\treturn metadata;\n\t\t}\n\t}\n}\n","sourceCodeStart":151,"sourceCodeEnd":181,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/skills/SkillMetadata.java#L151-L181","documentation":"SkillMetadata.Builder.build() validates that a skill loaded from a SKILL.md frontmatter has a non-empty description and throws IllegalStateException when it is missing or empty. The library requires every registered skill to advertise what it does, since descriptions are used by the model to decide when to invoke a skill. This is a fail-fast invariant check during skill metadata construction.","triggerScenarios":"Calling SkillMetadata.builder()...build() (directly or via a registry loading SKILL.md files) when the parsed frontmatter lacks the 'description' field or it is an empty string.","commonSituations":"A SKILL.md file in the skills directory omits the YAML frontmatter 'description:' key, has an empty description value, or malformed frontmatter caused the parser to leave description null.","solutions":["Add a non-empty 'description:' field to the skill's SKILL.md YAML frontmatter","Verify frontmatter delimiters (---) are intact so the description is actually parsed","Set description explicitly via SkillMetadata.builder().description(\"...\") when building programmatically"],"exampleFix":"// before (SKILL.md)\n---\nname: my-skill\n---\n// after\n---\nname: my-skill\ndescription: Performs X when the user asks for Y\n---","handlingStrategy":"validation","validationCode":"String desc = frontmatter.get(\"description\");\nif (desc == null || desc.isBlank()) throw new IllegalArgumentException(\"SKILL.md must define a non-empty description\");","typeGuard":"boolean hasDescription(SkillMetadata m) { return m.getDescription() != null && !m.getDescription().isEmpty(); }","tryCatchPattern":"try { metadata = builder.build(); } catch (IllegalStateException e) { log.error(\"Invalid skill metadata: {}\", e.getMessage()); skipSkill(); }","preventionTips":["Always include a meaningful description in every SKILL.md frontmatter","Add a startup test that builds metadata for all bundled skills","Lint SKILL.md files in CI for required frontmatter fields"],"tags":["skill","validation","frontmatter"],"backgroundTag":"missing-required-config-field","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}