{"record":{"id":"317f6512edeaf5f3","repo":"alibaba/spring-ai-alibaba","slug":"invalid-skill-path","errorCode":null,"errorMessage":"Invalid skill path: {}","messagePattern":"Invalid skill path: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/skills/registry/AbstractSkillRegistry.java","lineNumber":138,"sourceCode":"\t@Override\n\tpublic String readSkillContentByPath(String skillPath) throws IOException {\n\t\tif (skillPath == null || skillPath.isBlank()) {\n\t\t\tthrow new IllegalArgumentException(\"Skill path cannot be null or empty\");\n\t\t}\n\t\trequireNormalizedSkillPath(skillPath);\n\t\tSkillMetadata skill = getByPath(skillPath)\n\t\t\t\t.orElseThrow(() -> new IllegalStateException(\"Skill not found: \" + skillPath));\n\t\treturn skill.loadFullContent();\n\t}\n\n\tprotected abstract void loadSkillsToRegistry();\n\n\tprotected static String normalizeSkillPath(String skillPath) {\n\t\ttry {\n\t\t\treturn Path.of(skillPath).toAbsolutePath().normalize().toString();\n\t\t}\n\t\tcatch (InvalidPathException ex) {\n\t\t\tthrow new IllegalArgumentException(\"Invalid skill path: \" + skillPath, ex);\n\t\t}\n\t}\n\n\tprotected static String requireNormalizedSkillPath(String skillPath) {\n\t\tif (skillPath == null || skillPath.isBlank()) {\n\t\t\tthrow new IllegalArgumentException(\"Skill path cannot be null or empty\");\n\t\t}\n\t\treturn normalizeSkillPath(skillPath);\n\t}\n\n\tprivate Optional<SkillMetadata> findByPathInternal(String skillPath) {\n\t\tif (skillPath == null || skillPath.isBlank()) {\n\t\t\treturn Optional.empty();\n\t\t}\n\t\tfinal String normalized;\n\t\ttry {\n\t\t\tnormalized = normalizeSkillPath(skillPath);\n\t\t}","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/skills/registry/AbstractSkillRegistry.java#L120-L156","documentation":"AbstractSkillRegistry.normalizeSkillPath converts a skill path string to an absolute normalized Path; if the string is not a valid file-system path (contains NUL bytes or other illegal characters) Path.of throws InvalidPathException, which is rethrown as IllegalArgumentException with the offending path.","triggerScenarios":"Calling readSkillContentByPath or findByPath with a string that cannot be parsed as a Path (illegal characters such as NUL, platform-invalid sequences).","commonSituations":"LLM-generated path arguments containing garbage characters; concatenation bugs injecting separators/NUL bytes; Windows-illegal characters used on Windows; passing a URI/URL string instead of a file path.","solutions":["Sanitize/validate the path string before passing it (reject control characters)","Pass paths obtained from SkillMetadata.getSkillPath() rather than free-form strings","Strip URI prefixes like 'file://' and convert to a plain filesystem path","On Windows, check the path against platform-illegal characters"],"exampleFix":"// before\nregistry.readSkillContentByPath(\"file://\" + skillPath);\n// after\nregistry.readSkillContentByPath(Paths.get(URI.create(uri)).toString());","handlingStrategy":"validation","validationCode":"if (p != null && (p.indexOf('\\u0000') >= 0 || p.chars().anyMatch(Character::isISOControl))) throw new IllegalArgumentException(\"Path contains illegal characters\");","typeGuard":"boolean isParsablePath(String p) { try { if (p == null) return false; Path.of(p); return true; } catch (InvalidPathException e) { return false; } }","tryCatchPattern":"try { content = registry.readSkillContentByPath(p); } catch (IllegalArgumentException e) { log.warn(\"Invalid skill path '{}'\", p); }","preventionTips":["Sanitize any model-generated path before use","Do not concatenate URL/URI strings into filesystem paths","Run path normalization yourself early so failures surface at the boundary"],"tags":["path","validation","invalid-path"],"backgroundTag":"invalid-argument-format","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"}