{"record":{"id":"0a53f46ec0566ca6","repo":"alibaba/spring-ai-alibaba","slug":"targetfolder-s-must-be-a-directory","errorCode":null,"errorMessage":"targetFolder '%s' must be a directory","messagePattern":"targetFolder '(.+?)' must be a directory","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/file/FileSystemSaver.java","lineNumber":100,"sourceCode":"\t\t\t\t.stateSerializer(stateSerializer));\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tprotected FileSystemSaver(Builder builder) {\n\t\tStateSerializer stateSerializer = builder.stateSerializer;\n\t\tif (stateSerializer == null) {\n\t\t\tthis.serializer = new CheckPointSerializer(StateGraph.DEFAULT_JACKSON_SERIALIZER);\n\t\t}\n\t\telse {\n\t\t\tthis.serializer = new CheckPointSerializer(stateSerializer);\n\t\t}\n\t\tthis.targetFolder = Objects.requireNonNull(builder.targetFolder, \"targetFolder cannot be null\");\n\t\tthis.maxCachedThreads = builder.maxCachedThreads;\n\t\tthis.latestCheckpointCache = createLatestCheckpointCache(builder.maxCachedThreads);\n\n\t\ttry {\n\t\t\tif (Files.exists(this.targetFolder) && !Files.isDirectory(this.targetFolder)) {\n\t\t\t\tthrow new IllegalArgumentException(format(\"targetFolder '%s' must be a directory\", this.targetFolder));\n\t\t\t}\n\t\t\tFiles.createDirectories(this.targetFolder);\n\t\t}\n\t\tcatch (IOException ex) {\n\t\t\tthrow new IllegalArgumentException(format(\"targetFolder '%s' cannot be created\", this.targetFolder), ex);\n\t\t}\n\n\t}\n\n\t/**\n\t * Creates a new builder for FileSystemSaver.\n\t * @return a new Builder instance\n\t */\n\tpublic static Builder builder() {\n\t\treturn new Builder();\n\t}\n\n\tprivate String getBaseName(RunnableConfig config) {","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/file/FileSystemSaver.java#L82-L118","documentation":"FileSystemSaver persists checkpoints to a folder. During construction it verifies that the configured targetFolder either does not exist or is a directory; if the path exists as a regular file, IllegalArgumentException is thrown with the path in the message.","triggerScenarios":"new FileSystemSaver.Builder().targetFolder(Path.of(\"/some/file.txt\")) where that path already exists as a plain file, then build().","commonSituations":"Pointing the saver at a file (e.g. a config file or database file) instead of a directory, or a leftover file occupying the intended checkpoint directory path.","solutions":["Point targetFolder at a directory (existing or to-be-created), not a file","Delete or move the file occupying the path","Choose a different checkpoint directory"],"exampleFix":"// before\nFileSystemSaver.builder().targetFolder(Path.of(\"/data/checkpoints.db\")).build();\n// after\nFileSystemSaver.builder().targetFolder(Path.of(\"/data/checkpoints\")).build();","handlingStrategy":"validation","validationCode":"if (Files.exists(targetFolder) && !Files.isDirectory(targetFolder)) throw new IllegalArgumentException(\"not a directory: \" + targetFolder);","typeGuard":"boolean usableFolder(Path p) { return !Files.exists(p) || Files.isDirectory(p); }","tryCatchPattern":"try { FileSystemSaver.builder().targetFolder(p).build(); } catch (IllegalArgumentException e) { /* pick another folder */ }","preventionTips":["Always configure a directory path, never a file","Pre-create the directory at deployment time","Check for stray files at the configured path"],"tags":["filesystem","checkpoint","validation"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}