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 newView on GitHub (pinned to affd8760f4)
Solutions
- Read the wrapped path and io error to see exactly what failed.
- Fix permissions so the daemon user can read `<home>/etc/gateway-http.toml`.
- If the path is a directory or has bad encoding, remove/recreate it as a UTF-8 TOML file.
- 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
- Keep gateway-http.toml a regular, daemon-readable UTF-8 file.
- Never name a directory gateway-http.toml.
- Delete the file if you want the single-tenant default instead of fixing permissions.
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
- Failed to resolve Astrid home: {e}
- resolve AstridHome: {e}
- inspect legacy revocation file: {error}
- read materialized capsule metadata: {error:#}
- read materialized capsule authority: {error:#}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/8722889b4bed31cb.
Report an issue: GitHub.