ruvnet/RuView · error

cannot read {}: {e} — run `enroll` first

Error message

cannot read {}: {e} — run `enroll` first

What it means

train-room failed to std::fs::read_to_string the --enrollment JSON file; the message directs to 'run enroll first'. Typical io::Error kinds: NotFound (no enroll run yet or wrong path), permission denied, or InvalidData when the file is not valid UTF-8 — e.g. a binary baseline passed by mistake.

Source

Thrown at v2/crates/wifi-densepose-cli/src/room.rs:243

    pub enrollment: String,
    /// Output specialist-bank file.
    #[arg(long, default_value = "./room-bank.json")]
    pub output: String,
    /// Optional transceiver-geometry file: a JSON array of `NodeGeometry`
    /// records (ADR-152 §2.1.1). Recorded into the enrollment session before
    /// training so the bank carries the layout it was trained under.
    #[arg(long)]
    pub geometry: Option<String>,
}

/// Execute `train-room`.
///
/// If the enrollment session carries a transceiver-geometry snapshot (recorded
/// at enroll time or supplied here via `--geometry`), it is threaded into the
/// bank (ADR-152 §2.1.1); a geometry-free enrollment still trains a valid bank.
pub async fn train_room(args: TrainRoomArgs) -> Result<()> {
    let raw = std::fs::read_to_string(&args.enrollment)
        .map_err(|e| anyhow::anyhow!("cannot read {}: {e} — run `enroll` first", args.enrollment))?;
    let mut data: EnrollmentData =
        serde_json::from_str(&raw).map_err(|e| anyhow::anyhow!("invalid enrollment: {e}"))?;
    if data.anchors.is_empty() {
        bail!("no accepted anchors in {} — re-run enroll", args.enrollment);
    }

    if let Some(path) = &args.geometry {
        let graw = std::fs::read_to_string(path)
            .map_err(|e| anyhow::anyhow!("cannot read geometry {path}: {e}"))?;
        let geometry: Vec<NodeGeometry> = serde_json::from_str(&graw).map_err(|e| {
            anyhow::anyhow!("invalid geometry {path}: {e} (expected a JSON array of NodeGeometry records)")
        })?;
        data.session.record_geometry(geometry, now_unix());
    }

    let mut bank = SpecialistBank::train(&data.room_id, &data.baseline_id, &data.anchors, now_unix())
        .map_err(|e| anyhow::anyhow!("training failed: {e}"))?;
    match data.session.geometry() {

View on GitHub (pinned to 4685618388)

Solutions

  1. Run enroll and use the path it prints
  2. Pass the enrollment .json file, not the binary baseline
  3. Prefer absolute paths or a fixed working directory
  4. Fix read permissions if the file exists

Example fix

// before
$ ruview train-room --enrollment ./baseline.bin   # cannot read — run `enroll` first

// after
$ ruview enroll --output ./artifacts/enrollment.json
$ ruview train-room --enrollment ./artifacts/enrollment.json
Defensive patterns

Strategy: validation

Validate before calling

fn enrollment_readable(path: &str) -> bool {
    std::path::Path::new(path).is_file() && std::fs::read_to_string(path).is_ok()
}

Prevention

When it happens

Trigger: Running train-room before enroll produced the file; --enrollment pointing at the binary baseline instead of enrollment JSON; non-UTF-8 content; unreadable permissions.

Common situations: Workflow ordering mistakes across the calibrate, enroll, train-room chain; artifact-type mixups; relative paths breaking across working directories.

Related errors


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