dbt-labs/dbt-core · error · minijinja::Error (InvalidOperation)
Failed to remove stale directory {}: {}
Error message
Failed to remove stale directory {}: {} What it means
When the destination path itself is a stale directory (from a previous nested artifact layout) and the current resource writes a flat file, write_file removes the directory with remove_dir_all; failure raises this error with the path and OS error (e.g. permission denied or non-empty removal issues).
Source
Thrown at crates/dbt-jinja-utils/src/phases/run/run_node_context.rs:769
format!("Failed to remove stale file {}: {}", ancestor.display(), e),
));
}
break;
}
}
if let Err(e) = fs::create_dir_all(parent) {
return Err(Error::new(
ErrorKind::InvalidOperation,
format!("Failed to create directory {}: {}", parent.display(), e),
));
}
}
// A stale directory sitting where we now write a flat file fails with EISDIR.
if full_path.is_dir()
&& let Err(e) = fs::remove_dir_all(full_path)
{
return Err(Error::new(
ErrorKind::InvalidOperation,
format!(
"Failed to remove stale directory {}: {}",
full_path.display(),
e
),
));
}
match fs::write(full_path, payload) {
Ok(_) => Ok(()),
Err(e) => Err(Error::new(
ErrorKind::InvalidOperation,
format!("Failed to write to {}: {}", full_path.display(), e),
)),
}
}
View on GitHub (pinned to 0267ce9170)
Solutions
- Remove the stale directory manually using the path from the message: rm -rf <path>.
- Fix ownership/permissions of the target/ tree for the running user.
- Avoid concurrent runs sharing one target/ directory; use distinct --target-path or profiles per job.
- Close processes (watchers, editors, antivirus) holding handles inside the directory and rerun.
Example fix
// before # dbt run -> Failed to remove stale directory target/run/my_model: Permission denied // after sudo chown -R $(whoami) target/ && rm -rf target/run/my_model && dbt run
Defensive patterns
Strategy: try-catch
Try / catch
if full_path.is_dir() {
if let Err(e) = fs::remove_dir_all(full_path) {
if e.kind() == std::io::ErrorKind::PermissionDenied {
// hint: chown target/ and remove the stale directory manually
}
return Err(wrap(full_path, e));
}
} Prevention
- Delete target/ when switching between dbt versions with different artifact layouts.
- Never share one target/ directory across concurrent dbt processes.
- Keep target/ ownership consistent with the user running dbt.
When it happens
Trigger: full_path (e.g. target/run/some_model) is an existing directory from an earlier layout, and fs::remove_dir_all fails due to permissions, files held open by other processes, or a read-only filesystem.
Common situations: Upgrading/downgrading dbt versions where artifact layout changed; parallel processes racing on the same target/ directory; directories owned by a different user in shared CI workspaces.
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
- Failed to remove stale file {}: {}
- Failed to create directory {}: {}
- Failed to write file: {e}
- {type(df)} is not a supported type for dbt Python materializ
- {type(df)} is not a supported type for dbt Python materializ
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/f9693ae3d7e31f85.
Report an issue: GitHub.