unicity-aos/aos-ce · error · std::io::Error

cannot construct the bundled runtime PATH

Error message

cannot construct the bundled runtime PATH: {error}

What it means

runtime_child_path joins the bundled runtime bin directory with the host PATH via std::env::join_paths and wraps any join failure (invalid UTF-8/empty path entries, etc.) in an InvalidInput error formatted as "cannot construct the bundled runtime PATH: {error}". It exists because the child process must receive a PATH that prefers bundled tools.

Solutions

  1. Fix the host PATH environment variable: remove empty entries and invalid characters, then relaunch.
  2. Sanitize the host PATH before calling (filter out empty/non-UTF-8 components) instead of passing it through.
  3. Ensure runtime_bin is a valid non-empty directory path.

Example fix

// before
let host_path = std::env::var_os("PATH"); // contains empty entry
let p = runtime_child_path(&runtime_bin, host_path)?;
// after
let host_path = std::env::var_os("PATH")
    .map(|p| std::env::split_paths(&p).filter(|c| !c.as_os_str().is_empty()).collect::<Vec<_>>())
    .map(|v| std::env::join_paths(v).expect("sanitized PATH joins"));
let p = runtime_child_path(&runtime_bin, host_path)?;
Defensive patterns

Strategy: validation

Validate before calling

fn sanitized_host_path() -> Option<OsString> {
    std::env::var_os("PATH").map(|p| {
        std::env::join_paths(
            std::env::split_paths(&p).filter(|c| !c.as_os_str().is_empty()),
        ).expect("sanitized PATH should join")
    })
}

Try / catch

match result {
    Err(e) if e.to_string().starts_with("cannot construct the bundled runtime PATH") => {
        eprintln!("host PATH is malformed (empty entries or invalid characters); fix PATH and relaunch");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling runtime_child_path when either the runtime_bin path or an entry inside the host PATH cannot be joined — most commonly an empty path element or a path containing characters the platform disallows in PATH entries (join_paths returns JoinPathsError).

Common situations: A malformed host PATH containing empty entries ("::") or NUL bytes; inheriting PATH from a broken container/shell init; passing an empty runtime_bin PathBuf.

Understand the failure class

Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.

Related errors


AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13). Data as JSON: /api/errors/6a7f1a0e7bdede33. Report an issue: GitHub.

Appendix: source

Thrown at crates/unicity-aos-bootstrap/src/lib.rs:424

        if let Some(workspace) = workspace {
            args.push(OsString::from("--workspace"));
            args.push(workspace.as_os_str().to_owned());
        }
        if verbose {
            args.push(OsString::from("--verbose"));
        }
        let mut command = self.runtime_executable_command(&daemon_binary, args)?;
        command.env("ASTRID_DAEMON_LOG_TARGET", "stderr");
        Ok(command)
    }

    fn runtime_child_path(runtime_bin: &Path, host_path: Option<OsString>) -> io::Result<OsString> {
        let mut child_path = vec![runtime_bin.to_path_buf()];
        if let Some(host_path) = host_path {
            child_path.extend(std::env::split_paths(&host_path));
        }
        std::env::join_paths(child_path).map_err(|error| {
            io::Error::new(
                io::ErrorKind::InvalidInput,
                format!("cannot construct the bundled runtime PATH: {error}"),
            )
        })
    }

    /// Spawn the bundled runtime with its AOS-owned runtime home.
    ///
    /// # Errors
    /// Returns an error when the bundled executable is absent or cannot start.
    pub fn spawn_runtime(&self) -> io::Result<Child> {
        self.spawn_runtime_with_args(std::iter::empty::<&OsStr>())
    }

    /// Spawn the bundled runtime with runtime CLI arguments.
    ///
    /// This path uses the runtime's normal local operator credentials. The
    /// runtime home remains scoped to this AOS installation.

View on GitHub (pinned to f6f22024fb)