ruvnet/RuView · error · anyhow::Error
failed to create data_dir {}: {e}
Error message
failed to create data_dir {}: {e} What it means
`TrainingSession::new` runs `std::fs::create_dir_all` on the sanitized data dir. Any mkdir failure is reported with the target path: a path component already exists as a regular file, EACCES when the user cannot write an ancestor, or EROFS on a read-only filesystem. Sanitization has already passed at this point, so the cause is environmental, not traversal.
Source
Thrown at v2/crates/wifi-densepose-pointcloud/src/training.rs:167
near_clip: 0.3,
far_clip: 8.0,
gamma: 1.0,
samples_used: 0,
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(),View on GitHub (pinned to 4685618388)
Solutions
- Remove or rename the regular file blocking the path (`rm runs`) and retry.
- Choose a writable location (e.g. under `$HOME` or a mounted volume) or grant write permission on the ancestor / remount rw.
- Diagnose per-component with `namei -l <path>` to find where access stops.
Example fix
# before ruview-train --data-dir /mnt/usb/runs # read-only mount -> failed to create data_dir # after mount -o remount,rw /mnt/usb || ruview-train --data-dir /home/op/runs
Defensive patterns
Strategy: validation
Validate before calling
fn data_dir_creatable(raw: &str) -> bool {
let p = std::path::Path::new(raw);
// no component may already exist as a non-directory
let mut cur = std::path::PathBuf::new();
for c in p.components() {
cur.push(c);
if cur.exists() && !cur.is_dir() {
return false;
}
}
true
} Prevention
- Pre-create the data dir in provisioning (`mkdir -p`) so the API never has to.
- Avoid read-only mounts and system paths for data_dir; prefer $HOME or a mounted volume.
- Use `namei -l <path>` when creation fails to find the blocking component.
When it happens
Trigger: `runs.json` exists as a file and `runs.json/sub` is requested; unprivileged user targeting `/var/lib/ruview`; a read-only rootfs or ro-mounted USB stick at the target; SELinux denying dir creation.
Common situations: Embedded or container images with read-only rootfs and no writable volume; stale files occupying the intended directory name; wrong HOME when running under a service manager.
Related errors
- data_dir not accessible {}: {e}
- parent not accessible {}: {e}
- cannot write {output}: {e}
- cannot write {}: {e}
- cannot read {path}: {e}
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/95131776bdde668b.
Report an issue: GitHub.