ruvnet/RuView · error · anyhow::Error
parent not accessible {}: {e}
Error message
parent not accessible {}: {e} What it means
After rejecting `..` components and joining the child name onto `data_dir`, `safe_join` canonicalizes the *parent* of the joined path to prove containment. If that parent does not exist — typically because the child name contains a subdirectory that was never created (`subdir/frames.json` with no `subdir/`) — or is not accessible, or a path component meant to be a directory is actually a regular file (ENOTDIR), this error fires.
Source
Thrown at v2/crates/wifi-densepose-pointcloud/src/training.rs:59
}
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()))?,
))
}
/// Training data sample — a snapshot of the scene.
#[derive(Serialize, Deserialize)]
pub struct TrainingSample {
pub timestamp_ms: i64,
pub source: String,View on GitHub (pinned to 4685618388)
Solutions
- Create the intermediate directory yourself before the write: `std::fs::create_dir_all(data_dir.join("subdir"))?;`.
- Use flat, single-component filenames for children of data_dir.
- If the error text shows ENOTDIR, remove or rename the regular file occupying the parent-component name.
Example fix
// before
session.write_child("day1/frames.json", &data)?; // parent not accessible .../day1
// after
std::fs::create_dir_all(session.data_dir().join("day1"))?;
session.write_child("day1/frames.json", &data)?; Defensive patterns
Strategy: validation
Validate before calling
fn child_parent_ready(base: &std::path::Path, child: &str) -> bool {
let joined = base.join(child);
match joined.parent() {
Some(p) => p.is_dir(),
None => false,
}
} Prevention
- Only pass single-component filenames to safe_join'd write APIs; create subdirectories explicitly with create_dir_all first.
- Never name a file and later a directory with the same component — ENOTDIR is the tell.
- In tests, assert parent readiness before exercising write paths.
When it happens
Trigger: Writing `subdir/file.json` through the training API without creating `subdir` first; a nested name whose parent component collides with an existing regular file; concurrent processes renaming/removing directories between join and canonicalize.
Common situations: Callers assuming the API mkdirs intermediate directories (it deliberately does not); capture pipelines introducing date-scoped subpaths; leftover files occupying a directory name.
Related errors
- data_dir not accessible {}: {e}
- failed to create data_dir {}: {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/913e592c2b645df4.
Report an issue: GitHub.