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

  1. Check the wrapped IOException cause for the real reason (permission, existence)
  2. Create the directory manually and ensure write permissions for the process user
  3. Verify no parent path component is an existing regular file
  4. 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

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


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