astrid-runtime/astrid · error · anyhow::Error
channel state path has no parent
Error message
channel state path has no parent
What it means
When acquiring the channel lock, the state pointer path returned by state_paths() has no parent directory (a root-level or degenerate path). The lock code requires a directory to create the .{channel}.lock file in.
Solutions
- Fix the state-directory override so it points to a real subdirectory (e.g. ~/.astrid/channels)
- Unset the offending env var to fall back to the default state path
- Ensure the configured path is not the filesystem root
Example fix
// before ASTRID_STATE_DIR=/ astrid update // after ASTRID_STATE_DIR=$HOME/.astrid astrid update
Defensive patterns
Strategy: validation
Validate before calling
if state_dir == "/" || state_dir.is_empty() {
return Err("state dir must be a real subdirectory".into());
} Try / catch
match acquire_channel_lock(channel) {
Ok(lock) => /* proceed */,
Err(e) if e.to_string().contains("no parent") => eprintln!("fix your state-dir configuration: {e}"),
Err(e) => return Err(e),
} Prevention
- Never point state dirs at "/" or empty paths
- Use the library's default state location unless you have a reason
- Validate env overrides at startup
When it happens
Trigger: acquire_channel_lock computes state_paths(channel) and pointer_path.parent() returns None — only possible if the configured state path is a bare root or empty filename, typically from a bad ASTRID state-dir override.
Common situations: An environment variable or config overriding the channel state directory to "/" or an empty/relative bare path; an embedding launcher passing a malformed state root.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- AlreadyExists
- AlreadyExists
- Astrid durable media is redirected or not a regular file
- Astrid home without a layout sentinel is redirected or not…
- Astrid volume is already open
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/10bda2dd6373cf99.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-cli/src/commands/update_channel.rs:714
Ok((
dir.join(format!("{}.toml", channel.as_str())),
dir.join(format!("{}.toml.sigstore.json", channel.as_str())),
))
}
struct ChannelLock(std::fs::File);
impl Drop for ChannelLock {
fn drop(&mut self) {
let _ = FileExt::unlock(&self.0);
}
}
fn acquire_channel_lock(channel: UpdateChannel) -> anyhow::Result<ChannelLock> {
let (pointer_path, _) = state_paths(channel)?;
let dir = pointer_path
.parent()
.ok_or_else(|| anyhow::anyhow!("channel state path has no parent"))?;
std::fs::create_dir_all(dir).context("could not create channel state directory")?;
let lock_path = dir.join(format!(".{}.lock", channel.as_str()));
let lock = std::fs::OpenOptions::new()
.create(true)
.read(true)
.write(true)
.truncate(false)
.open(&lock_path)
.context("could not open channel update lock")?;
lock.try_lock_exclusive()
.context("another Astrid process is already resolving this channel")?;
Ok(ChannelLock(lock))
}
pub(super) fn enforce_continuity(
channel: UpdateChannel,
candidate: &ChannelPointer,
candidate_bytes: &[u8],View on GitHub (pinned to affd8760f4)