astrid-runtime/astrid · error
MCP gateway is already running at
Error message
MCP gateway is already running at {} What it means
Fired by prepare_gateway_socket when the gateway socket path exists and a Unix-stream probe successfully connects to it — meaning another live gateway process already owns the endpoint. Binding a second listener would silently steal or fail against the existing owner.
Solutions
- Use the already-running gateway instead of starting a new one (`astrid mcp status`)
- Stop the existing gateway before restarting
- Remove a stale socket only after confirming no process is listening
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at crates/astrid-cli/src/commands/mcp/lifecycle.rs:384 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/859e2d0f06a627d1.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-cli/src/commands/mcp/lifecycle.rs:384
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
std::fs::set_permissions(path, std::fs::Permissions::from_mode(0o700))?;
}
Ok(())
}
/// Bind-time cleanup and endpoint ownership check for a gateway listener.
pub(crate) async fn prepare_gateway_socket(_lifecycle: &GatewayLifecycleLock) -> Result<PathBuf> {
let path = gateway_socket_path()?;
let parent = path
.parent()
.ok_or_else(|| anyhow::anyhow!("MCP gateway socket path has no parent"))?;
ensure_private_dir(parent)?;
if path.exists() {
if UnixStream::connect(&path).await.is_ok() {
anyhow::bail!("MCP gateway is already running at {}", path.display());
}
// The lifecycle lock excludes every gateway generation. If the
// pathname survived a crash, this holder is now the only process that
// may remove and replace it.
std::fs::remove_file(&path).with_context(|| {
format!(
"failed to remove stale MCP gateway socket {}",
path.display()
)
})?;
}
Ok(path)
}
/// Wait for a ready gateway, starting one child at most once when absent.
pub(crate) async fn wait_for_gateway(principal: &PrincipalId, format: &str) -> Result<ExitCode> {
let format = ReadyFormat::parse(format)?;
let socket = gateway_socket_path()?;View on GitHub (pinned to affd8760f4)