alibaba/spring-ai-alibaba · error · IllegalArgumentException
targetFolder '%s' cannot be created
Error message
targetFolder '%s' cannot be created
What it means
FileSystemSaver construction creates the targetFolder if missing via Files.createDirectories. If that fails with IOException (e.g. permission denied, parent is a file, disk error), it rethrows as IllegalArgumentException wrapping the original exception.
Source
Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/file/FileSystemSaver.java:105
StateSerializer stateSerializer = builder.stateSerializer;
if (stateSerializer == null) {
this.serializer = new CheckPointSerializer(StateGraph.DEFAULT_JACKSON_SERIALIZER);
}
else {
this.serializer = new CheckPointSerializer(stateSerializer);
}
this.targetFolder = Objects.requireNonNull(builder.targetFolder, "targetFolder cannot be null");
this.maxCachedThreads = builder.maxCachedThreads;
this.latestCheckpointCache = createLatestCheckpointCache(builder.maxCachedThreads);
try {
if (Files.exists(this.targetFolder) && !Files.isDirectory(this.targetFolder)) {
throw new IllegalArgumentException(format("targetFolder '%s' must be a directory", this.targetFolder));
}
Files.createDirectories(this.targetFolder);
}
catch (IOException ex) {
throw new IllegalArgumentException(format("targetFolder '%s' cannot be created", this.targetFolder), ex);
}
}
/**
* Creates a new builder for FileSystemSaver.
* @return a new Builder instance
*/
public static Builder builder() {
return new Builder();
}
private String getBaseName(RunnableConfig config) {
var threadId = config.threadId().orElse(THREAD_ID_DEFAULT);
return format("thread-%s", threadId);
}
private Path getPath(RunnableConfig config) {View on GitHub (pinned to f82da0b50f)
Solutions
- Check the wrapped IOException cause for the real reason (permission, existence)
- Create the directory manually and ensure write permissions for the process user
- Verify no parent path component is an existing regular file
- Run the app with a user that owns or can write to the target location
Example fix
// before
Files.setPosixFilePermissions(dir, PosixFilePermissions.fromString("r--------"));
// after
Files.createDirectories(dir);
Files.setPosixFilePermissions(dir, PosixFilePermissions.fromString("rwx------")); Defensive patterns
Strategy: validation
Validate before calling
Files.createDirectories(targetFolder); // run and handle IOException before building the saver
Type guard
boolean canCreate(Path p) { Path parent = p.toAbsolutePath().getParent(); return parent != null && Files.isDirectory(parent) && Files.isWritable(parent); } Try / catch
try { new FileSystemSaver(builder); } catch (IllegalArgumentException e) { handleCreateFailure(e.getCause()); } Prevention
- Verify volume writability before startup
- Ensure parent path components are directories
- Create the folder in deployment scripts with correct ownership
When it happens
Trigger: Building a FileSystemSaver whose targetFolder does not exist and cannot be created: unwritable parent, parent path component is a file, or filesystem errors.
Common situations: Read-only containers/volumes, wrong user permissions, path collisions where a parent segment is an existing file, network mounts unavailable.
Understand the failure class
Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.
Related errors
- targetFolder '%s' must be a directory
- maxCachedThreads must be greater than or equal to 0
- Got error when creating files
- Got error when creating files
- Path traversal not allowed
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/9abc4b4b576f6285.
Report an issue: GitHub.