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

  1. Create the intermediate directory yourself before the write: `std::fs::create_dir_all(data_dir.join("subdir"))?;`.
  2. Use flat, single-component filenames for children of data_dir.
  3. 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

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


AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16). Data as JSON: /api/errors/913e592c2b645df4. Report an issue: GitHub.