ruvnet/RuView · error · anyhow::Error
data_dir not accessible {}: {e}
Error message
data_dir not accessible {}: {e} What it means
`safe_join`, used by every filesystem write in the training module, canonicalizes the session's `data_dir` root to verify containment. If `base.canonicalize()` fails — the directory no longer exists, a component lacks search (execute) permission, or a symlink loop exists — the write is aborted with this error carrying the OS cause.
Source
Thrown at v2/crates/wifi-densepose-pointcloud/src/training.rs:53
/// through user-supplied names.
fn safe_join(base: &Path, child: &str) -> Result<PathBuf> {
// Reject absolute children and any `..` components up front.
let child_path = Path::new(child);
if child_path.is_absolute() {
return Err(anyhow!("child path must be relative: {child}"));
}
for comp in child_path.components() {
if matches!(comp, std::path::Component::ParentDir) {
return Err(anyhow!("child path may not contain `..`: {child}"));
}
}
let joined = base.join(child_path);
// Canonicalise base (must exist) and verify joined starts with it. If the
// joined file doesn't exist yet we canonicalise the parent.
let canonical_base = base
.canonicalize()
.map_err(|e| anyhow!("data_dir not accessible {}: {e}", base.display()))?;
let canonical_parent = joined
.parent()
.ok_or_else(|| anyhow!("no parent for {}", joined.display()))?;
let canonical_parent = canonical_parent
.canonicalize()
.map_err(|e| anyhow!("parent not accessible {}: {e}", canonical_parent.display()))?;
if !canonical_parent.starts_with(&canonical_base) {
return Err(anyhow!(
"refusing to write outside data_dir: {}",
joined.display()
));
}
Ok(canonical_parent.join(
joined
.file_name()
.ok_or_else(|| anyhow!("no filename for {}", joined.display()))?,
))
}View on GitHub (pinned to 4685618388)
Solutions
- Recreate the directory and rebuild the session: `mkdir -p <data_dir>` then a fresh `TrainingSession::new(...)`.
- Verify the dir is searchable by the same user running the session: `sudo -u <user> ls <data_dir>`.
- For removable/network roots, confirm the mount is present before issuing writes.
Example fix
// before
session.save()?; // data_dir deleted underneath -> "data_dir not accessible"
// after
if !std::path::Path::new(&dir).is_dir() {
std::fs::create_dir_all(&dir)?;
}
let session = TrainingSession::new(&dir)?;
session.save()?; Defensive patterns
Strategy: validation
Validate before calling
// Before any write API on a long-lived session.
fn data_dir_alive(dir: &std::path::Path) -> bool {
dir.is_dir() && dir.canonicalize().is_ok()
} Try / catch
match session.append(frame) {
Err(e) if e.downcast_ref::<std::io::Error>()
.map(|io| io.kind() == std::io::ErrorKind::NotFound)
.unwrap_or(false) =>
{
// data_dir vanished: recreate and rebuild the session, then retry once
std::fs::create_dir_all(dir)?;
let session = TrainingSession::new(&dir)?;
session.append(frame)
}
r => r,
} Prevention
- Keep the data_dir's lifetime tied to the session's; never `rm -rf` it mid-capture.
- Prefer local filesystems over network mounts for data_dir during training.
- Run the writer under the uid that owns the dir.
When it happens
Trigger: The data dir was deleted after `TrainingSession::new` succeeded; a network mount (NFS/SMB) dropped between session creation and a write; permission revocation on an ancestor directory; symlink cycles inside the path.
Common situations: `rm -rf` of the output dir mid-session (common in test harnesses); unmounted USB/NFS roots; running the writer under a different uid than the creator; container volume remounts.
Related errors
- parent not accessible {}: {e}
- failed to create data_dir {}: {e}
- cannot canonicalise data_dir {}: {e}
- cannot write {output}: {e}
- cannot write {}: {e}
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/34d9f3850d89b980.
Report an issue: GitHub.