alibaba/spring-ai-alibaba · error · IllegalStateException

Skill not found: {}

Error message

Skill not found: {}

What it means

readSkillContent throws IllegalStateException when get(name) finds no skill matching the given name in the registry. Unlike a normal lookup API that returns Optional, this read API treats a missing skill as an exceptional state because the caller explicitly asked for one skill's full content.

Source

Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/skills/registry/filesystem/FileSystemSkillRegistry.java:241

	 * Get the user skills directory path.
	 * This is an implementation-specific method, not part of the SkillRegistry interface.
	 *
	 * @return the user skills directory path
	 */
	public String getUserSkillsDirectory() {
		return userSkillsDirectory;
	}

	@Override
	public String readSkillContent(String name) throws IOException {
		if (name == null || name.isEmpty()) {
			throw new IllegalArgumentException("Skill name cannot be null or empty");
		}

		// Get the skill by name
		Optional<SkillMetadata> skillOpt = get(name);
		if (skillOpt.isEmpty()) {
			throw new IllegalStateException("Skill not found: " + name);
		}

		SkillMetadata skill = skillOpt.get();

		// Use the normal loadFullContent method for filesystem skills
		return skill.loadFullContent();
	}

	@Override
	public String getSkillLoadInstructions() {
		List<SkillMetadata> skills = listAll();
		List<SkillMetadata> userSkills = new ArrayList<>();
		List<SkillMetadata> projectSkills = new ArrayList<>();
		for (SkillMetadata skill : skills) {
			if ("project".equals(skill.getSource())) {
				projectSkills.add(skill);
			}
			else {

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Verify the exact skill name via registry.list()/search before reading
  2. Check the configured user/project skills directories contain the skill
  3. Ensure the registry is initialized and skills are loaded before reading

Example fix

// before
String content = registry.readSkillContent("code-review");
// after
if (registry.get("code-review").isPresent()) {
    String content = registry.readSkillContent("code-review");
} else {
    // handle missing skill
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (name != null && registry.get(name).isPresent()) { /* safe to read */ }

Try / catch

try { content = registry.readSkillContent(name); } catch (IllegalStateException e) { log.warn("Skill missing: {}", name); return null; }

Prevention

When it happens

Trigger: Calling readSkillContent with a name that is not registered: typo in skill name, skill directory absent from the configured skills directories, skill disabled/hidden and filtered out by the registry, or registry not initialized/loaded before the call.

Common situations: Renaming a skill directory but not the referencing code; passing a skill description or path instead of the skill name; skills directory misconfigured (wrong path) so the skill was never loaded; calling before auto-load of skills completes.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09). Data as JSON: /api/errors/c4b2f06962fe2800. Report an issue: GitHub.