ruvnet/RuView · error
cannot create output dir {}: {e}
Error message
cannot create output dir {}: {e} What it means
std::fs::create_dir_all failed for the calibrate-serve --output-dir at HTTP API startup. It is an OS-level io::Error: permission denied on a path component, a component that already exists as a regular file, an invalid path string, or an I/O error on the volume. The server aborts before binding any socket.
Source
Thrown at v2/crates/wifi-densepose-cli/src/calibrate_api.rs:315
.route("/api/v1/calibration/health", get(health))
.route("/api/v1/calibration/start", post(start))
.route("/api/v1/calibration/status", get(status_handler))
.route("/api/v1/calibration/stop", post(stop))
.route("/api/v1/calibration/result", get(result))
.route("/api/v1/calibration/baselines", get(baselines))
.route("/api/v1/room/state", get(room_state))
.route("/api/v1/room/train", post(train_room))
.route("/api/v1/enroll/anchor", post(enroll_anchor))
.route("/api/v1/enroll/geometry", post(enroll_geometry))
.route("/api/v1/enroll/status", get(enroll_status))
.layer(CorsLayer::permissive())
.with_state(state)
}
/// Run the calibration HTTP API server (blocks until Ctrl-C).
pub async fn execute(args: CalibrateServeArgs) -> Result<()> {
std::fs::create_dir_all(&args.output_dir)
.map_err(|e| anyhow::anyhow!("cannot create output dir {}: {e}", args.output_dir))?;
let udp_addr = format!("{}:{}", args.udp_bind, args.udp_port);
let socket = UdpSocket::bind(&udp_addr)
.await
.map_err(|e| anyhow::anyhow!("cannot bind UDP socket on {udp_addr}: {e}"))?;
eprintln!("[calibrate-serve] CSI ingest on udp://{udp_addr}");
let status = Arc::new(RwLock::new(SharedStatus {
udp_port: args.udp_port,
default_tier: args.tier.clone(),
output_dir: args.output_dir.clone(),
..Default::default()
}));
let (cmd_tx, cmd_rx) = mpsc::channel::<CalCommand>(8);
let window = Arc::new(RwLock::new(VecDeque::<f32>::with_capacity(LIVE_WINDOW)));
let enroll = Arc::new(RwLock::new(HashMap::<String, RoomEnroll>::new()));
View on GitHub (pinned to 4685618388)
Solutions
- Manually run mkdir -p as the same user the server runs as to surface the exact OS error
- Remove or rename the regular file occupying the path
- Point --output-dir to a writable volume or mount one at that path
- Fix ownership/permissions on the parent directory (chown/chmod)
Example fix
// before $ ruview calibrate-serve --output-dir /var/lib/ruview/baselines # create_dir_all fails // after $ mkdir -p /var/lib/ruview/baselines && chown $(id -u) /var/lib/ruview/baselines $ ruview calibrate-serve --output-dir /var/lib/ruview/baselines
Defensive patterns
Strategy: validation
Validate before calling
fn ensure_output_dir(path: &str) -> Result<(), String> {
let p = std::path::Path::new(path);
if p.exists() && !p.is_dir() {
return Err(format!("{path} exists and is not a directory"));
}
std::fs::create_dir_all(p).map_err(|e| format!("cannot create {path}: {e}"))
} Prevention
- Pre-create the output dir in deployment units (systemd ExecStartPre, container entrypoint) before the server starts
- Mount a writable volume at the configured output path in containers
- Avoid root-owned --output-dir paths when the service runs unprivileged
When it happens
Trigger: Starting calibrate-serve with --output-dir whose parent is not writable; --output-dir naming an existing regular file; a read-only mount (container rootfs); a path containing an invalid component.
Common situations: Container images where the data volume is not mounted at the configured path; CI or services running as non-root against root-owned paths; a previous run leaving a file where the directory is expected.
Related errors
- cannot write {output}: {e}
- cannot read baseline {path}: {e} — run `calibrate` first
- HOMECORE_TOKENS is required; use --insecure-dev-auth only fo
- invalid automations file {}: {e}
- failed to initialize ruvector index: {error}
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/786be58f463bf6f4.
Report an issue: GitHub.