{"record":{"id":"77e2566631a62477","repo":"alibaba/spring-ai-alibaba","slug":"failed-to-delete","errorCode":null,"errorMessage":"Failed to delete: {}","messagePattern":"Failed to delete: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/tools/ShellSessionManager.java","lineNumber":353,"sourceCode":"\t * Check if a session is registered for the given threadId. Package-private for testing.\n\t */\n\tstatic boolean isSessionInRegistry(String threadId) {\n\t\treturn SESSION_REGISTRY.containsKey(threadId);\n\t}\n\n\tpublic Long getMaxOutputBytes() {\n\t\treturn maxOutputBytes;\n\t}\n\n\tprivate void deleteDirectory(Path directory) throws IOException {\n\t\tif (Files.exists(directory)) {\n\t\t\ttry (var stream = Files.walk(directory)) {\n\t\t\t\tstream.sorted(Comparator.reverseOrder())\n\t\t\t\t\t.forEach(path -> {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tFiles.delete(path);\n\t\t\t\t\t\t} catch (IOException e) {\n\t\t\t\t\t\t\tlog.warn(\"Failed to delete: {}\", path, e);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Persistent shell session that executes commands sequentially.\n\t * <p>This is a static nested class to avoid implicit reference to the outer\n\t * {@link ShellSessionManager} instance, which could cause memory leaks when\n\t * sessions are stored in the static {@link #SESSION_REGISTRY}.</p>\n\t */\n\tprivate static class ShellSession {\n\t\tprivate static final Logger log = LoggerFactory.getLogger(ShellSession.class);\n\t\tprivate static final String DONE_MARKER_PREFIX = \"__LC_SHELL_DONE__\";\n\n\t\tprivate final Path workspace;\n\t\tprivate final List<String> command;","sourceCodeStart":335,"sourceCodeEnd":371,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/tools/ShellSessionManager.java#L335-L371","documentation":"During deleteDirectory (invoked from doCleanup), an individual file or directory could not be deleted by Files.delete; the warning logs the offending path with the IOException and continues walking, so cleanup is best-effort rather than atomic.","triggerScenarios":"Files.walk cleanup encountering a locked file (process still holding it open), a file deleted concurrently, or OS-level permission denial on some path under the session working directory.","commonSituations":"Deleting a shell session temp dir while the spawned shell process still runs; Windows file locking; read-only mounts; other sessions sharing the same scratch directory.","solutions":["Ensure the shell process for the session is stopped/terminated before doCleanup runs.","Check filesystem permissions on the session working directory and its children.","Avoid sharing one scratch directory across concurrent sessions.","If deletion is advisory only, treat this as non-fatal; otherwise retry cleanup after a short delay."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if (!Files.isWritable(directory)) log.warn(\"Cleanup will likely fail on {}\", directory);","typeGuard":null,"tryCatchPattern":"try { cleanup(); } catch (Exception e) { log.warn(\"Session cleanup incomplete; residual files may remain\", e); }","preventionTips":["Terminate the shell process before deleting its working directory.","Use one scratch directory per session, never shared.","On Windows, watch for file locking; delay deletion until handles are released."],"tags":["filesystem","cleanup","io"],"backgroundTag":"file-write-failed","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"}