{"record":{"id":"eae7bf99a5176e7b","repo":"alibaba/spring-ai-alibaba","slug":"skill-name-is-required","errorCode":null,"errorMessage":"Skill name is required","messagePattern":"Skill name 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":166,"sourceCode":"\n\t\tpublic Builder source(String source) {\n\t\t\tmetadata.source = source;\n\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":148,"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#L148-L181","documentation":"SkillMetadata's builder enforces required fields at build() time: name, description, and skillPath must be non-null and non-empty. A missing name aborts construction with IllegalStateException, since a skill without a name is unidentifiable and unusable by the skill registry.","triggerScenarios":"Calling SkillMetadata.builder()...build() without invoking .name(...), or passing null/empty string to name().","commonSituations":"Programmatic skill construction where the name comes from parsed frontmatter or config that was empty; refactors dropping the name() call; YAML/JSON skill definitions missing the name key.","solutions":["Call .name(\"...\") with a non-empty value on the builder before build()","If the name originates from frontmatter/config, validate it is present before constructing SkillMetadata","Provide a default/derived name (e.g. from the skill directory name) when the source is missing","Add a startup check that iterates skill definitions and fails fast with a clear message when name is blank"],"exampleFix":"// before\nSkillMetadata meta = SkillMetadata.builder().description(\"d\").skillPath(\"skills/x\").build();\n// after\nSkillMetadata meta = SkillMetadata.builder().name(\"x\").description(\"d\").skillPath(\"skills/x\").build();","handlingStrategy":"validation","validationCode":"if (name == null || name.isBlank()) throw new IllegalArgumentException(\"Skill name is required\");","typeGuard":"boolean canBuildSkill(String name, String description, String path) {\n    return name != null && !name.isEmpty() && description != null && !description.isEmpty() && path != null && !path.isEmpty();\n}","tryCatchPattern":"SkillMetadata skill;\ntry { skill = builder.build(); } catch (IllegalStateException e) { if (e.getMessage().contains(\"Skill name is required\")) { skill = builder.name(deriveNameFromPath()).build(); } else throw e; }","preventionTips":["Validate skill frontmatter/config (name, description, path) before building SkillMetadata","Derive fallback names from directory names when sources may be incomplete","Fail fast at skill-loading startup with aggregated validation reports"],"tags":["validation","skills","builder"],"backgroundTag":"missing-required-argument","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}