loco-rs/loco · error
Failed to bind to address
Error message
Failed to bind to address
What it means
get_available_port binds a TcpListener to the TEST_BINDING_SERVER address with port 0 to let the OS pick a free port. If the bind fails — address family/hostname unresolvable, networking unavailable, or (on exotic setups) the resolver rejects it — the .expect panics with 'Failed to bind to address'.
Solutions
- Verify loopback networking works in the environment (ping/curl localhost, check /etc/hosts has 127.0.0.1 localhost).
- If TEST_BINDING_SERVER resolves oddly, ensure it maps to 127.0.0.1 (fix /etc/hosts or use an explicit IP).
- Enable networking in the CI container (remove --network none / add loopback support).
- Check seccomp/AppArmor or sandbox profiles that block socket() or bind() syscalls and allow them.
- As a fallback, parse the port from an explicitly bound 127.0.0.1:0 listener before calling the helper.
Example fix
// before
let addr = format!("{TEST_BINDING_SERVER}:0");
let listener = TcpListener::bind(addr).await.expect("Failed to bind to address");
// after
let addr = format!("{TEST_BINDING_SERVER}:0");
let listener = TcpListener::bind(&addr).await
.or_else(|_| tokio::net::TcpListener::bind("127.0.0.1:0"))
.await
.expect("Failed to bind to any test address"); Defensive patterns
Strategy: try-catch
Validate before calling
// precheck before running tests
match tokio::net::TcpListener::bind("127.0.0.1:0").await {
Ok(l) => drop(l),
Err(e) => panic!("loopback bind unavailable in this environment: {e}"),
} Try / catch
match TcpListener::bind(format!("{TEST_BINDING_SERVER}:0")).await {
Ok(listener) => { /* proceed */ }
Err(e) => eprintln!("skip test: cannot bind test listener: {e}"),
} Prevention
- Ensure /etc/hosts maps localhost to 127.0.0.1 in CI containers
- Enable loopback networking in sandboxed runners (--network != none)
- Allow socket bind syscalls in seccomp/AppArmor profiles
- Pin the binding host to an explicit IP when hostname resolution is flaky
When it happens
Trigger: Calling get_available_port() (directly or via the request test helpers) when TcpListener::bind("{TEST_BINDING_SERVER}:0") fails: the hostname does not resolve, IPv6/IPv4 mismatch in restricted containers, or no loopback networking (some sandboxes/CI without network namespaces configured).
Common situations: CI runners with networking disabled or restricted; Docker containers run with --network none; hostname resolution differences between macOS/Linux where 'localhost' resolution is blocked; corporate firewalls or seccomp profiles blocking socket bind.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- Failed to get local address
- db connection should success
- create DB schema
- create cleanup runtime
- Drop database
AI-assisted analysis of loco-rs/loco@23639d1e36 (2026-09-12).
Data as JSON: /api/errors/3c95cf584b1870f0.
Report an issue: GitHub.
Appendix: source
Thrown at src/testing/request.rs:157
/// The hostname to which the test server binds.
pub const TEST_BINDING_SERVER: &str = "localhost";
/// Constructs and returns the base URL used for the test server.
#[must_use]
pub fn get_base_url_port(port: i32) -> String {
format!("http://{TEST_BINDING_SERVER}:{port}/")
}
/// Returns a unique port number. Usually increments by 1 starting from 59126
///
/// # Panics
///
/// Will panic if binding to test server address fails or if getting the local address fails
pub async fn get_available_port() -> i32 {
let addr = format!("{TEST_BINDING_SERVER}:0");
let listener = TcpListener::bind(addr)
.await
.expect("Failed to bind to address");
i32::from(
listener
.local_addr()
.expect("Failed to get local address")
.port(),
)
}
/// Bootstraps test application with test environment hard coded.
///
/// # Example
///
/// The provided example demonstrates how to boot the test case with the
/// application context.
///
/// ```rust,ignore
/// use myapp::app::App;View on GitHub (pinned to 23639d1e36)