ruvnet/RuView · error · anyhow::Error
cannot canonicalise data_dir {}: {e}
Error message
cannot canonicalise data_dir {}: {e} What it means
Immediately after creating it, `TrainingSession::new` canonicalizes the data dir so `safe_join` has a fixed containment root. Failure here means the directory could not be resolved after creation: it vanished between `create_dir_all` and `canonicalize`, a parent denies traversal, or the path traverses a symlink loop / flaky FUSE-automount. It is rare and usually indicates a race or an exotic filesystem rather than a config mistake.
Source
Thrown at v2/crates/wifi-densepose-pointcloud/src/training.rs:171
rmse: f32::MAX,
}
}
}
impl TrainingSession {
/// Create a new training session rooted at `data_dir`.
///
/// `data_dir` must not contain `..` components — we reject path traversal
/// attempts from CLI/API input. The directory is created if missing and
/// then canonicalised so every subsequent write stays inside it.
pub fn new(data_dir: &str) -> Result<Self> {
let path = sanitize_data_path(data_dir)?;
std::fs::create_dir_all(&path)
.map_err(|e| anyhow!("failed to create data_dir {}: {e}", path.display()))?;
// Canonicalise so path-traversal checks in safe_join have a fixed root.
let path = path
.canonicalize()
.map_err(|e| anyhow!("cannot canonicalise data_dir {}: {e}", path.display()))?;
// Load existing calibration if available
let cal_path = safe_join(&path, "calibration.json")
// safe_join needs the parent to exist; for initial load that's always data_dir
.or_else(|_| Ok::<_, anyhow::Error>(path.join("calibration.json")))?;
let calibration = if cal_path.exists() {
let data = std::fs::read_to_string(&cal_path)?;
serde_json::from_str(&data).unwrap_or_default()
} else {
DepthCalibration::default()
};
Ok(Self {
samples: Vec::new(),
calibration,
data_dir: path,
})
}View on GitHub (pinned to 4685618388)
Solutions
- Retry session creation once the interfering cleanup stops (typically succeeds on the second attempt).
- Pass a stable, symlink-free absolute path for the data dir.
- Keep the data dir on a local, always-mounted filesystem during capture/training runs.
Example fix
// before
let s = TrainingSession::new(&dir)?; // cleaner deletes dir between mkdir and canonicalize
// after
let s = TrainingSession::new(&dir)
.or_else(|_| TrainingSession::new(&dir))?; // retry once after the race window Defensive patterns
Strategy: retry
Validate before calling
fn data_dir_resolvable(dir: &std::path::Path) -> bool {
dir.is_dir() && dir.canonicalize().is_ok()
} Try / catch
let session = match TrainingSession::new(&dir) {
Ok(s) => s,
Err(e) if e.to_string().contains("cannot canonicalise data_dir") => {
// transient race or flaky mount: recreate once, then retry
std::fs::create_dir_all(&dir)?;
TrainingSession::new(&dir)?
}
Err(e) => return Err(e),
}; Prevention
- Don't run cleanup jobs that wipe the output dir concurrently with session creation.
- Pass symlink-free absolute paths for data_dir.
- Keep data_dir off automounted FUSE/NFS roots during capture runs.
When it happens
Trigger: A concurrent cleaner (`rm -rf` in a test harness) deleting the fresh dir; cyclic symlinks in the path; transient FUSE/automount errors; NFS stale file handles immediately after creation.
Common situations: Test suites that wipe output dirs while sessions start; overlayfs quirks inside containers; NAS-backed data roots with aggressive automount timeouts.
Related errors
- data_dir not accessible {}: {e}
- parent not accessible {}: {e}
- failed to create data_dir {}: {e}
- cannot write {output}: {e}
- cannot create output dir {}: {e}
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/7ede84fbe4fe7e11.
Report an issue: GitHub.