alibaba/spring-ai-alibaba · warning · IllegalArgumentException

Path must start with one of :

Error message

Path must start with one of : 

What it means

After traversal checks and normalization, FilesystemInterceptor.validatePath() enforces an allow-list: when allowedPrefixes is non-empty, the normalized path must start with at least one prefix or it throws IllegalArgumentException("Path must start with one of <prefixes>: <path>"). This constrains filesystem operations to approved directory trees.

Source

Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/extension/interceptor/FilesystemInterceptor.java:183

		// Normalize path
		String normalized = path.replace("\\", "/");
		normalized = Paths.get(normalized).normalize().toString().replace("\\", "/");

		if (!normalized.startsWith("/")) {
			normalized = "/" + normalized;
		}

		// Check allowed prefixes if specified
		if (allowedPrefixes != null && !allowedPrefixes.isEmpty()) {
			boolean hasValidPrefix = false;
			for (String prefix : allowedPrefixes) {
				if (normalized.startsWith(prefix)) {
					hasValidPrefix = true;
					break;
				}
			}
			if (!hasValidPrefix) {
				throw new IllegalArgumentException(
					"Path must start with one of " + allowedPrefixes + ": " + path
				);
			}
		}

		return normalized;
	}

	@Override
	public List<ToolCallback> getTools() {
		return tools;
	}

	@Override
	public String getName() {
		return "Filesystem";
	}

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Add the required directory to the allowedPrefixes list passed to validatePath().
  2. Ensure the path and prefixes are normalized identically (same absolute form, separators, no trailing slash mismatch).
  3. Derive prefixes from configuration and log them at startup to spot drift.
  4. Anchor user input under an allowed root (root.resolve(input).normalize()) before validation.

Example fix

// before
validatePath("/var/tmp/out.txt", List.of("/srv/workspace")); // rejected

// after
validatePath("/srv/workspace/out.txt", List.of("/srv/workspace")); // ok
Defensive patterns

Strategy: validation

Validate before calling

String normalized = Paths.get(path.replace('\\', '/')).normalize().toString();
boolean allowed = allowedPrefixes.stream().anyMatch(normalized::startsWith);
if (!allowed) throw new IllegalArgumentException("Path outside allowed prefixes");

Type guard

boolean withinPrefixes(String path, List<String> prefixes) {
    String n = Paths.get(path.replace('\\', '/')).normalize().toString();
    return prefixes.stream().anyMatch(n::startsWith);
}

Try / catch

try {
    String canonical = FilesystemInterceptor.validatePath(path, prefixes);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Path must start with")) {
        log.error("Path {} outside allowed prefixes {}", path, prefixes);
    }
    throw e;
}

Prevention

When it happens

Trigger: validatePath("/var/data/file.txt", List.of("/srv/workspace")) — the normalized path does not begin with any configured allowed prefix.

Common situations: Misconfigured allowed-prefixes (missing the directory the app actually uses); paths expressed with trailing slashes or relative forms that don't string-match the configured prefix; moving code to a new deployment layout without updating prefixes.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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