loco-rs/loco · error
Failed to get local address
Error message
Failed to get local address
What it means
After binding, get_available_port calls listener.local_addr() to discover the OS-assigned port and .expect()s the result. If the local address cannot be retrieved the panic message is 'Failed to get local address'. This is rare — it usually indicates the socket was already closed or an OS-level socket error occurred.
Solutions
- Check ulimit -n / fd exhaustion if running many tests concurrently; raise the limit or reduce parallelism.
- Retry get_available_port() — the failure is typically transient/environmental.
- Verify the runtime environment supports getsockname on loopback sockets (gVisor/sandbox configs).
- Update the runtime/tokio and OS packages; check for known socket bugs in the container runtime.
Defensive patterns
Strategy: retry
Validate before calling
// precheck fd headroom
let free: i64 = std::fs::read_to_string("/proc/sys/fs/file-nr")
.ok()
.and_then(|s| s.split_whitespace().next().and_then(|n| n.parse().ok()))
.unwrap_or(0);
assert!(free < 1_000_000, "file descriptors near exhaustion"); Try / catch
let port = (0..3).find_map(|_| get_available_port_safe()).unwrap_or_else(|| {
panic!("could not obtain a local port after retries")
}); Prevention
- Raise ulimit -n in CI when running large parallel test suites
- Retry port acquisition on transient socket errors
- Keep the listener alive until after local_addr() is read
- Test container/network-stack compatibility (gVisor etc.) once in CI setup
When it happens
Trigger: Calling get_available_port() and having listener.local_addr() return Err: the listener was dropped/closed before the call, an OS socket error (fd exhaustion, EBADF), or an unusual network stack that cannot report the address.
Common situations: File-descriptor exhaustion under heavy parallel test load; custom network stacks (gVisor, some containers) with incomplete getsockname support; tokio runtime shutdown racing the helper; patched/virtualized loopback devices.
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 bind to 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/da1b65f4edafa650.
Report an issue: GitHub.
Appendix: source
Thrown at src/testing/request.rs:162
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;
/// use loco_rs::testing::prelude::*;
///
/// #[tokio::test]
/// async fn test_create_user() {
/// let boot = boot_test::<App>().await;View on GitHub (pinned to 23639d1e36)