astrid-runtime/astrid · error

an already-bound plain-HTTP listener cannot serve native TLS

Error message

an already-bound plain-HTTP listener cannot serve native TLS

What it means

Fires in run_with_capability_probe_on_listener: the caller handed in an already-bound plain TCP listener while GatewayState has a TLS config; TLS termination needs its own accept loop, so serving native TLS over that listener is refused rather than serving plaintext while believing it's TLS.

Solutions

  1. Bind the gateway through the TLS-aware startup path when config.tls is set
  2. Clear the tls config block if plaintext HTTP on this listener is actually intended
  3. Terminate TLS in a fronting proxy and run the gateway plain
Defensive patterns

Strategy: fallback

When it happens

Trigger: Thrown at crates/astrid-gateway/src/lib.rs:183 when the library encounters an invalid state.

Common situations: See trigger scenarios.

Understand the failure class


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

Appendix: source

Thrown at crates/astrid-gateway/src/lib.rs:183

}

/// Run the gateway on an already-bound plain-HTTP listener.
///
/// # Errors
/// Returns an error when native TLS is configured, the listener address is
/// unavailable, or the HTTP server fails.
#[doc(hidden)]
pub async fn run_with_capability_probe_on_listener<F>(
    state: Arc<GatewayState>,
    listener: TcpListener,
    shutdown: impl Future<Output = ()> + Send + 'static,
    capability_probe: F,
) -> Result<()>
where
    F: Fn(&astrid_core::PrincipalId, Option<&str>, &str) -> bool + Send + Sync + 'static,
{
    if state.config.tls.is_some() {
        anyhow::bail!("an already-bound plain-HTTP listener cannot serve native TLS");
    }
    let addr = listener
        .local_addr()
        .context("failed to read pre-bound gateway listener address")?;
    warn_if_plaintext_non_loopback(addr);
    state.hydrate_revocations().await?;
    let workspace_root = std::env::current_dir().unwrap_or_else(|_| std::path::PathBuf::from("."));
    serve_http_listener(
        state,
        listener,
        shutdown,
        workspace_root,
        astrid_core::dirs::WorkspaceLayout::default(),
        routes::events::CapabilityProbe::new(capability_probe),
    )
    .await
}

View on GitHub (pinned to affd8760f4)