Hmbown/CodeWhale · error
failed to enter ACP session cwd {}: {err}
Error message
failed to enter ACP session cwd {}: {err} What it means
When an ACP session is created, the server temporarily chdir()s into the client-provided cwd via ScopedCurrentDir. std::env::set_current_dir failed for that path; the message names the path and the OS reason (No such file or directory, Permission denied, Not a directory). The process working directory is left unchanged (the guard restores the prior dir on drop).
Source
Thrown at crates/tui/src/acp_server.rs:2082
"sessionId": session_id,
"update": update
}
});
write_json_line(writer, notification).await
}
struct ScopedCurrentDir {
prior: PathBuf,
}
impl ScopedCurrentDir {
fn new(cwd: &PathBuf) -> Result<Self> {
let prior = std::env::current_dir()?;
if cwd.as_os_str().is_empty() {
return Ok(Self { prior });
}
std::env::set_current_dir(cwd)
.map_err(|err| anyhow!("failed to enter ACP session cwd {}: {err}", cwd.display()))?;
Ok(Self { prior })
}
}
impl Drop for ScopedCurrentDir {
fn drop(&mut self) {
let _ = std::env::set_current_dir(&self.prior);
}
}
impl AcpError {
fn invalid_params(message: impl Into<String>) -> Self {
Self {
code: -32602,
message: message.into(),
}
}
View on GitHub (pinned to 8880682c63)
Solutions
- Check the cwd exists and is a directory before sending session/new (fs::metadata / Path::is_dir)
- Recreate or re-open the workspace folder, then retry the session
- Fix mount state or permissions for the path
- Send an empty cwd to run in the server's current directory instead
Example fix
// before
let cwd = std::path::PathBuf::from(request.cwd.clone());
let guard = ScopedCurrentDir::new(&cwd)?;
// after
let cwd = std::path::PathBuf::from(request.cwd.clone());
if !cwd.as_os_str().is_empty() && !cwd.is_dir() {
anyhow::bail!("session cwd does not exist or is not a directory: {}", cwd.display());
}
let guard = ScopedCurrentDir::new(&cwd)?; Defensive patterns
Strategy: validation
Validate before calling
let cwd = std::path::PathBuf::from(session_cwd.clone());
if !cwd.as_os_str().is_empty() {
let meta = std::fs::metadata(&cwd)
.map_err(|err| anyhow::anyhow!("session cwd {} unreadable: {err}", cwd.display()))?;
if !meta.is_dir() {
anyhow::bail!("session cwd is not a directory: {}", cwd.display());
}
} Type guard
fn is_usable_session_cwd(cwd: &std::path::Path) -> bool {
cwd.as_os_str().is_empty() || cwd.is_dir()
} Try / catch
match ScopedCurrentDir::new(&cwd) {
Ok(guard) => { /* session body */ }
Err(err) if err.to_string().starts_with("failed to enter ACP session cwd") => {
return AcpError::invalid_params(format!("cwd unusable: {}", cwd.display()));
}
Err(err) => return Err(err),
} Prevention
- Verify the workspace folder still exists right before session/new; editors can hold stale paths after the folder is deleted or moved
- Ensure network/remote mounts are attached before starting a session that uses them
- Send an empty cwd when the server's current directory is acceptable
- Reject file paths and unreadable directories early with invalid_params instead of letting chdir fail
When it happens
Trigger: session/new with a cwd that was deleted after the client opened it, a path on an unmounted network/remote drive, a path that names a file rather than a directory, or missing execute/search permission on a path component. An empty cwd is accepted and means 'stay in the current directory'.
Common situations: Editor workspace deleted or moved while the session starts; WSL/SSHFS/network mounts not yet attached; sandboxed runners without traversal permission; clients forwarding stale workspace paths from restored state.
Related errors
- resolving external credential path: {err}
- Codewhale credentials directory must be owned by the current
- could not inspect {}: {error}
- Failed to write MCP config {}: {}
- Release asset directory must be flat; found: ${nonFiles.map(
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/7f01f0ed8fe43a54.
Report an issue: GitHub.