t8y2/dbx · critical
Failed to bind address
Error message
Failed to bind address
What it means
Panics/aborts in dbx-web main when binding the HTTP listener to 0.0.0.0:DBX_PORT (default 4224) fails — the port is already in use or lacks bind permissions. The server cannot accept connections, so startup terminates after logging the bind failure.
Source
Thrown at crates/dbx-web/src/main.rs:1125
let static_dir = std::env::var_os("DBX_STATIC_DIR").map(std::path::PathBuf::from);
app = mount_public_base_path(app, &public_base_path, static_dir.as_deref());
// Bind address
let port: u16 = std::env::var("DBX_PORT").ok().and_then(|p| p.parse().ok()).unwrap_or(4224);
let addr = SocketAddr::from(([0, 0, 0, 0], port));
tracing::info!("DBX Web server starting on http://{}", addr);
if public_base_path != "/" {
tracing::info!("Serving DBX Web under context path {}", public_base_path);
}
if password_disabled {
tracing::info!("Password protection is disabled");
} else if std::env::var("DBX_PASSWORD").is_ok() {
tracing::info!("Password protection is enabled");
}
let listener = tokio::net::TcpListener::bind(addr).await.expect("Failed to bind address");
let shutdown_state = web_state.app.clone();
axum::serve(listener, app)
.with_graceful_shutdown(async {
if let Err(error) = tokio::signal::ctrl_c().await {
tracing::warn!("Failed to listen for shutdown signal: {error}");
}
})
.await
.expect("Server error");
shutdown_state.shutdown(std::time::Duration::from_secs(3)).await;
}
#[cfg(test)]
mod tests {
use super::{
mount_public_base_path, normalize_public_base_path, web_agent_dir_from_env, web_body_limit_bytes_from_value,
web_compression_predicate, XLSX_CONTENT_TYPE,
};View on GitHub (pinned to c0390bff16)
Solutions
- Free the port: find and stop the process using it (lsof -i :PORT / netstat) or choose a different port via DBX_PORT.
- Set DBX_HOST to 0.0.0.0 (or a valid local IP) and a non-privileged port, or grant binding capabilities.
- Check IPv6 availability if binding '::' — use '0.0.0.0' on IPv4-only hosts.
- Configure SO_REUSEADDR equivalent or ensure a graceful shutdown of the previous instance before restart.
Example fix
// before
let listener = tokio::net::TcpListener::bind(addr).await.expect("Failed to bind address");
// after
let listener = tokio::net::TcpListener::bind(&addr).await
.unwrap_or_else(|e| panic!("Failed to bind address {}: {e}", addr)); Defensive patterns
Strategy: validation
Validate before calling
use std::net::TcpListener;
fn port_free(addr: &str) -> bool {
addr.to_socket_addrs().ok()
.and_then(|mut a| a.next())
.map(|a| TcpListener::bind(a).is_ok())
.unwrap_or(false)
}
// call before starting: assert!(port_free("127.0.0.1:8080")); Try / catch
match tokio::net::TcpListener::bind(&addr).await {
Ok(l) => l,
Err(e) if e.kind() == std::io::ErrorKind::AddrInUse => {
eprintln!("Port in use at {addr}; stop the other process or change DBX_PORT");
std::process::exit(1);
}
Err(e) => { eprintln!("Failed to bind {addr}: {e}"); std::process::exit(1); }
} Prevention
- Check the port with lsof/netstat before deploying or restarting.
- Use non-privileged ports (>1024) or grant binding capabilities.
- Use 0.0.0.0 unless a specific interface is required.
- Coordinate port allocation across replicas via env config.
When it happens
Trigger: TcpListener::bind(addr) fails because the port is already in use, the address is not a local interface, or the process lacks permission to bind (e.g., privileged port <1024 without capabilities).
Common situations: Another instance of dbx-web (or a leftover process) holding the port; DBX_HOST/DBX_PORT set to a bad or in-use combination; binding port 80/443 as non-root in a container; IPv6 address specified on a host without IPv6.
Related errors
- DBX_PUBLIC_BASE_PATH contains invalid characters
- error while building tauri application: {error}
- Failed to install rustls crypto provider
- Failed to create data directory
- Failed to open storage
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/5f2d168b10f57bba.
Report an issue: GitHub.