alibaba/spring-ai-alibaba · error · IOException

Path is not a directory:

Error message

Path is not a directory: 

What it means

AgentSpecLoader.loadFromDirectory requires the given Path to be an existing directory containing .md agent spec files. If the path exists but is a regular file (or another non-directory type), an IOException with 'Path is not a directory: ...' is thrown. This is a fail-fast guard before walking the tree.

Solutions

  1. Pass the directory containing the .md agent spec files, not an individual file.
  2. Validate with Files.isDirectory(path) before calling; if you need to load a single file, use AgentSpecLoader.loadFromResource instead.
  3. Check the configured path property in application config for typos or accidental file paths.

Example fix

// before
List<AgentSpec> specs = AgentSpecLoader.loadFromDirectory(Path.of("agents/spec.md"));
// after
List<AgentSpec> specs = AgentSpecLoader.loadFromDirectory(Path.of("agents/"));
Defensive patterns

Strategy: validation

Validate before calling

if (path == null || !Files.isDirectory(path)) throw new IllegalArgumentException("Expected a directory: " + path);

Type guard

boolean isSpecDir(Path p) { return p != null && Files.isDirectory(p); }

Prevention

When it happens

Trigger: Calling AgentSpecLoader.loadFromDirectory(path) where Files.exists(path) is true but Files.isDirectory(path) is false — e.g. passing a single .md file path instead of the spec directory.

Common situations: Developers point the loader at one agent markdown file instead of its folder; a config property meant to hold a directory accidentally contains a file path; symlinks resolve to files.

Related errors


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

Appendix: source

Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/tools/task/AgentSpecLoader.java:84

	 * @return list of parsed specs
	 */
	public static List<AgentSpec> loadFromDirectory(String directoryPath) throws IOException {
		if (!StringUtils.hasText(directoryPath)) {
			return List.of();
		}
		return loadFromDirectory(Paths.get(directoryPath));
	}

	/**
	 * Load agent specs from a directory (recursively scans for .md files).
	 */
	public static List<AgentSpec> loadFromDirectory(Path rootPath) throws IOException {
		if (rootPath == null || !Files.exists(rootPath)) {
			logger.warn("Agent spec directory does not exist: {}", rootPath);
			return List.of();
		}
		if (!Files.isDirectory(rootPath)) {
			throw new IOException("Path is not a directory: " + rootPath);
		}

		List<AgentSpec> specs = new ArrayList<>();
		try (Stream<Path> paths = Files.walk(rootPath)) {
			paths.filter(Files::isRegularFile)
					.filter(p -> p.getFileName().toString().endsWith(".md"))
					.forEach(path -> {
						try {
							AgentSpec spec = loadFromFile(path);
							if (spec != null) {
								specs.add(spec);
								logger.debug("Loaded agent spec: {} from {}", spec.name(), path);
							}
						}
						catch (Exception e) {
							logger.warn("Failed to load agent spec from {}: {}", path, e.getMessage());
						}
					});

View on GitHub (pinned to f82da0b50f)