astrid-runtime/astrid · error
{VARIABLE} {detail}
Error message
{VARIABLE} {detail} What it means
Astrid validates the ASTRID_RUN_DIR environment variable before using it and rejects malformed values with io::ErrorKind::InvalidInput. The message is `{VARIABLE} {detail}` where VARIABLE is the literal env var name; known details include: the value must not be empty, must be an absolute path, and must not contain '.' or '..' path components.
Source
Thrown at crates/astrid-core/src/dirs_run_dir.rs:73
let physical_run = physical_path(&path)?;
let physical_root = physical_path(home.root())?;
if paths_are_related(&physical_run, &physical_root)
|| directories_are_aliases(&physical_run, &physical_root)
{
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"{VARIABLE} overlaps the Astrid durable root: {} overlaps {}",
path.display(),
home.root().display()
),
));
}
Ok(Some(physical_run))
}
fn invalid(detail: &str) -> io::Error {
io::Error::new(io::ErrorKind::InvalidInput, format!("{VARIABLE} {detail}"))
}
fn physical_path(path: &Path) -> io::Result<PathBuf> {
if let Ok(physical) = std::fs::canonicalize(path) {
return Ok(physical);
}
let mut missing = Vec::new();
let mut existing_parent = path;
while matches!(
std::fs::symlink_metadata(existing_parent),
Err(error) if error.kind() == io::ErrorKind::NotFound
) {
let Some(name) = existing_parent.file_name() else {
break;
};
missing.push(name.to_os_string());
existing_parent = existing_parent.parent().expect("parent checked above");
}View on GitHub (pinned to affd8760f4)
Solutions
- Set ASTRID_RUN_DIR to a non-empty, absolute path with no '.' or '..' components, e.g. /run/astrid
- Normalize the value in your deploy config: resolve variables before export (`export ASTRID_RUN_DIR="$(realpath -m "$BASE/run")"`) and guard against empty expansion
- Unset ASTRID_RUN_DIR entirely to use the default (home root + `run`) if you do not need a custom location
Example fix
// before export ASTRID_RUN_DIR=astrid/run/../tmp # relative + '..' // after export ASTRID_RUN_DIR=/var/run/astrid # absolute, clean components
Defensive patterns
Strategy: validation
Validate before calling
fn run_dir_value_ok(raw: &std::ffi::OsStr) -> bool {
let p = std::path::PathBuf::from(raw);
!raw.is_empty() && p.is_absolute()
&& !p.components().any(|c| matches!(c, std::path::Component::ParentDir | std::path::Component::CurDir))
} Try / catch
match std::env::var_os("ASTRID_RUN_DIR") {
Some(v) if !run_dir_value_ok(&v) => {
eprintln!("ASTRID_RUN_DIR must be a non-empty absolute path without '.'/'..'; using default");
std::env::remove_var("ASTRID_RUN_DIR");
},
_ => {},
} Prevention
- Export ASTRID_RUN_DIR as an absolute, fully expanded path in shells and manifests
- Normalize templated values with realpath -m before export
- Guard against empty expansion (`${VAR:?}` in shell) when the variable may be unset
When it happens
Trigger: ASTRID_RUN_DIR set to an empty string; set to a relative path like `run` or `./run`; or containing `.`/`..` components such as /var/run/../astrid. Raised by the `invalid` helper inside `resolved`, called from configured_path/validate at startup.
Common situations: Shell exports ASTRID_RUN_DIR='' (e.g. `export ASTRID_RUN_DIR=;` or unexpanded variable); Docker/K8s env uses a relative path; a templated config produces /var/lib/../run/astrid.
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
- {} is not a real directory: {}
- {} overlaps the Astrid durable root: {} overlaps {}
- groups path has no parent directory
- layout path is redirected or not a directory: {}
- live Astrid volume has no parent
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/3da2c1f0a31f8579.
Report an issue: GitHub.