alibaba/spring-ai-alibaba · warning

Failed to delete temporary directory: {}

Error message

Failed to delete temporary directory: {}

What it means

ShellSessionManager.doCleanup deletes the session's temporary workspace directory when the session was created with a temporary workspace (useTemporaryWorkspace). If deleteDirectory throws IOException, this warning is logged with the directory path and the cleanup continues by removing SESSION_PATH_CONTEXT_KEY from the context. The temp dir may then be left on disk as an orphan.

Source

Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/tools/ShellSessionManager.java:203

				session = registryEntry.session();
				tempDir = registryEntry.workspacePath();
				log.debug("Removed shell session from global registry for threadId: {}", config.threadId().get());
			}
		} else if (session != null && config.threadId().isPresent()) {
			// Also remove from registry if we found it in context
			SESSION_REGISTRY.remove(config.threadId().get());
		}

		if (session != null) {
			session.stop(terminationTimeout);
			config.context().remove(SESSION_INSTANCE_CONTEXT_KEY);
		}

		if (tempDir != null && useTemporaryWorkspace) {
			try {
				deleteDirectory(tempDir);
			} catch (IOException e) {
				log.warn("Failed to delete temporary directory: {}", tempDir, e);
			}
			config.context().remove(SESSION_PATH_CONTEXT_KEY);
		}
	}

	/**
	 * Attempt to recover a shell session from the global registry.
	 * This is used during HITL resume when the original context is lost.
	 *
	 * @param config the runnable config containing threadId
	 * @return the recovered session, or null if not found
	 */
	private ShellSession recoverSessionFromRegistry(RunnableConfig config) {
		return config.threadId().map(threadId -> {
			SessionEntry entry = SESSION_REGISTRY.get(threadId);
			if (entry != null) {
				log.info("Recovered shell session from global registry for threadId: {}. " +
						"Shell state (working directory, environment) is preserved.", threadId);

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Ensure all child processes of the shell session are terminated before cleanup so file handles are released.
  2. Check filesystem permissions/ownership of the temp directory (java.io.tmpdir) for the user running the agent.
  3. Monitor for the warning and add an external reaper (cron/task) to sweep orphaned temp dirs as a safety net.
  4. Set a custom, writable workspace path instead of the default temporary workspace if the platform's tmpdir is restricted.

Example fix

// before
// processes still alive when doCleanup runs
session.close();
// after
session.close();
process.children().forEach(ProcessHandle::destroyForcibly); // release file locks
// then doCleanup deletes tempDir successfully
Defensive patterns

Strategy: validation

Validate before calling

static void verifyDeletable(Path dir) throws IOException {
    if (dir == null || !Files.exists(dir)) return;
    if (!Files.isWritable(dir)) throw new IOException("No write permission on temp dir: " + dir);
}

Try / catch

try {
    deleteDirectory(tempDir);
} catch (IOException e) {
    log.warn("Failed to delete temporary directory: {}", tempDir, e);
    // schedule for later cleanup or reaper
}

Prevention

When it happens

Trigger: doCleanup (called from cleanup) attempts Files-style recursive deletion of tempDir and an IOException occurs — files locked or still being written by a lingering child process, permission problems, or a directory removed externally mid-deletion.

Common situations: 1) A spawned background process from the shell session still holding files open in the temp workspace. 2) Running agents as different users (e.g. containerized) without delete permission on the created dir. 3 Read-only filesystems or disk-full edge cases. 4 Temp dirs accumulating because this warning repeats and nobody notices.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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