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

must be an absolute path

Error message

{variable} must be an absolute path

What it means

validated_environment_root requires the root path to be absolute; a relative PathBuf triggers an InvalidInput io error "{variable} must be an absolute path", after which validate_path_entry performs further checks. Absolute paths are mandatory so runtime layout and private-directory creation cannot depend on the process's current working directory.

Solutions

  1. Prefix the value with "/" (or a drive root) in the environment: use an absolute path like /opt/myapp/runtime.
  2. Canonicalize in the launcher script, e.g. export MYAPP_ROOT="$(pwd)/data".
  3. Reject relative values at config-load time with a clear message before the process starts.

Example fix

// before
export MYAPP_ROOT=data/runtime
// after
export MYAPP_ROOT=/var/lib/myapp/runtime
Defensive patterns

Strategy: validation

Validate before calling

fn require_absolute_env_path(name: &str) -> Result<PathBuf, String> {
    let v = std::env::var_os(name).ok_or_else(|| format!("{name} not set"))?;
    let p = PathBuf::from(&v);
    if p.as_os_str().is_empty() { return Err(format!("{name} is empty")); }
    if !p.is_absolute() { return Err(format!("{name} must be absolute, got {:?}", p)); }
    Ok(p)
}

Type guard

fn is_absolute_path(v: &OsStr) -> bool {
    !v.is_empty() && Path::new(v).is_absolute()
}

Try / catch

match validated_environment_root(root, "MYAPP_ROOT") {
    Err(e) if e.to_string().contains("must be an absolute path") => {
        eprintln!("fix MYAPP_ROOT in the unit file/script to start with /");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Setting a root environment variable to a relative path like "runtime" or "./data" and passing it through validated_environment_root.

Common situations: Writing VAR=data in a shell script assuming the daemon's cwd; copying an example config that used a relative path; launching the process from an unexpected working directory so a previously-working relative value now resolves elsewhere.

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/d121637c0228133d. Report an issue: GitHub.

Appendix: source

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

    }

    fn from_environment_root(root: OsString, variable: &str) -> io::Result<Self> {
        Ok(Self::from_root(Self::validated_environment_root(
            root, variable,
        )?))
    }

    fn validated_environment_root(root: OsString, variable: &str) -> io::Result<PathBuf> {
        if root.is_empty() {
            return Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                format!("{variable} must not be empty"),
            ));
        }

        let root = PathBuf::from(root);
        if !root.is_absolute() {
            return Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                format!("{variable} must be an absolute path"),
            ));
        }
        validate_path_entry(&root, variable)?;
        Ok(root)
    }

    /// Build an AOS home from an explicit root, useful for embedding and tests.
    #[must_use]
    pub fn from_root(root: impl Into<PathBuf>) -> Self {
        Self { root: root.into() }
    }

    /// The product-owned AOS root.
    #[must_use]
    pub fn root(&self) -> &Path {
        &self.root

View on GitHub (pinned to f6f22024fb)