astrid-runtime/astrid · error · anyhow::Error

read {}: {e}

Error message

read {}: {e}

What it means

`load_gateway_config` reads `<astrid-home>/etc/gateway-http.toml` with `tokio::fs::read_to_string`. A NotFound error is tolerated (single-tenant default, Ok(None)), but any other I/O error — permission denied, is-a-directory, invalid UTF-8 — is propagated as `read <path>: <cause>`.

Source

Thrown at crates/astrid-daemon/src/lib.rs:486

#[expect(
    clippy::unused_async,
    reason = "the cross-platform daemon entry point remains async even when startup is unsupported"
)]
pub async fn run() -> Result<()> {
    anyhow::bail!("native Astrid daemon startup is not yet supported on this platform")
}

/// Load `etc/gateway-http.toml`. Returns `Ok(None)` when the file
/// doesn't exist (single-tenant default).
#[cfg(unix)]
async fn load_gateway_config() -> Result<Option<astrid_gateway::GatewayConfig>> {
    let home = astrid_core::dirs::AstridHome::resolve()
        .map_err(|e| anyhow::anyhow!("resolve AstridHome: {e}"))?;
    let path = home.etc_dir().join("gateway-http.toml");
    let text = match tokio::fs::read_to_string(&path).await {
        Ok(b) => b,
        Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(None),
        Err(e) => return Err(anyhow::anyhow!("read {}: {e}", path.display())),
    };
    let cfg: astrid_gateway::GatewayConfig =
        toml::from_str(&text).context("parse gateway-http.toml")?;
    cfg.validate().context("validate gateway-http.toml")?;
    Ok(Some(cfg))
}

#[cfg(unix)]
fn spawn_gateway(
    cfg: astrid_gateway::GatewayConfig,
    kernel: &std::sync::Arc<astrid_kernel::Kernel>,
) -> Result<std::sync::Arc<tokio::sync::Notify>> {
    // Plumb four kernel handles into the gateway:
    //
    //   * the event bus, so the SSE audit stream and the bus-direct
    //     admin client can subscribe / publish locally without going
    //     back over the Unix socket;
    //   * the persistent audit log, so the new

View on GitHub (pinned to affd8760f4)

Solutions

  1. Read the wrapped path and io error to see exactly what failed.
  2. Fix permissions so the daemon user can read `<home>/etc/gateway-http.toml`.
  3. If the path is a directory or has bad encoding, remove/recreate it as a UTF-8 TOML file.
  4. If you don't need the gateway config, delete the file — absence is the supported single-tenant default.

Example fix

// before
$ ls -l ~/.astrid/etc/gateway-http.toml
-rw------- root root
// after
$ sudo chown astrid:astrid ~/.astrid/etc/gateway-http.toml
$ chmod 600 ~/.astrid/etc/gateway-http.toml
Defensive patterns

Strategy: try-catch

Validate before calling

// shell
F="$HOME/.astrid/etc/gateway-http.toml"
if [ -e "$F" ]; then [ -f "$F" ] && [ -r "$F" ] && iconv -f utf-8 -t utf-8 "$F" >/dev/null || exit 1; fi

Try / catch

// rust
match load_gateway_config().await {
    Ok(None) => { /* no file: use single-tenant default */ }
    Ok(Some(cfg)) => { /* use cfg */ }
    Err(e) => { eprintln!("{e:#}"); /* path and io cause are in the message */ }
}

Prevention

When it happens

Trigger: Calling `load_gateway_config()` when gateway-http.toml exists but cannot be read: wrong permissions, path is a directory, or file contains invalid UTF-8.

Common situations: Tightened permissions after an audit; a directory accidentally named gateway-http.toml; editor saving the file in a non-UTF-8 encoding.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/8722889b4bed31cb. Report an issue: GitHub.