gitbutlerapp/gitbutler · error
Failed to bind to
Error message
Failed to bind to {url}: {e} What it means
Public `run` in but-server binds a `tokio::net::TcpListener` to `host:port` (from config `bind_addr`, env `BUTLER_HOST`, or default 127.0.0.1, plus the chosen port) before serving the axum app. If the bind fails, the error is logged (with a special hint when the cause is `AddrInUse`) and re-raised as "Failed to bind to {url}: {e}", so the server never starts.
Solutions
- Stop the existing process holding the port (find it with `lsof -i :<port>` on Unix or `netstat -ano` on Windows) or use another port.
- Set the port/host via config `bind_addr` or the BUTLER_HOST env var to a valid local address.
- If binding a privileged port, run with the required permissions or pick a port >= 1024.
- Retry after transient bind failures, or add automatic port selection if the fixed port is expected to be free.
Example fix
// before BUTLER_HOST=0.0.0.0 but-server --port 8585 // port taken by running instance // after lsof -ti :8585 | xargs kill # or: BUTLER_HOST=127.0.0.1 but-server --port 8586
Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight: check the port is free before starting the server ss -ltn | grep -q ':<port> ' && echo 'port in use' || echo 'port free'
Type guard
fn is_addr_in_use(err: &anyhow::Error) -> bool {
err.chain().any(|c| {
c.downcast_ref::<std::io::Error>()
.map(|io| io.kind() == std::io::ErrorKind::AddrInUse)
.unwrap_or(false)
})
} Try / catch
match but_server::run(config).await {
Err(e) if e.to_string().contains("Failed to bind") && is_addr_in_use(&e) => {
// stop the existing instance or restart with a different port
}
other => other?,
} Prevention
- Check for a running but-server instance before starting another one.
- Make the port configurable (config bind_addr / BUTLER_HOST) and avoid hardcoding ports in scripts.
- Use a port >= 1024 unless you have the privileges for a well-known port.
- Validate the bind address is a valid local interface before launching.
- Add automatic port selection or retry-with-next-port logic in orchestration scripts.
When it happens
Trigger: Starting the server via `run` when `TcpListener::bind` fails: the port is already taken by another but-server/other process (AddrInUse), the port is privileged (<1024) without permission, the bind address is invalid or not local, or the port range is exhausted.
Common situations: Launching a second instance while one is already running (most common — the log explicitly hints at this); another service squatting on the port; typo'd BUTLER_HOST/bind_addr; docker/container networking where the address isn't assignable.
Related errors
- Anthropic API error ( )
- Bitbucket pagination exceeded the
- Bitbucket request failed
- Bitbucket request failed
- Download failed with HTTP status
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/e7aac9027fd4a442.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-server/src/lib.rs:848
let default_host = "127.0.0.1";
let host_env = std::env::var("BUTLER_HOST").ok();
let host = config
.bind_addr
.as_deref()
.or(host_env.as_deref())
.unwrap_or(default_host);
let url = format!("{host}:{port}");
let listener = match tokio::net::TcpListener::bind(&url).await {
Ok(listener) => listener,
Err(e) => {
if e.kind() == std::io::ErrorKind::AddrInUse {
tracing::error!(
"Failed to bind to {url}: {e}. Another instance of but-server may already be running on port {port}."
);
} else {
tracing::error!("Failed to bind to {url}: {e}");
}
anyhow::bail!("Failed to bind to {url}: {e}");
}
};
println!(
"{} {}",
"Local:".bold(),
format!("http://localhost:{port}").cyan().underline()
);
let server = axum::serve(
listener,
app.into_make_service_with_connect_info::<SocketAddr>(),
);
tokio::select! {
result = server => { result.unwrap(); }
_ = tokio::signal::ctrl_c() => {
// The settings file watcher (spawn_blocking with infinite loop) and
// other background tasks prevent the tokio runtime from exiting
// cleanly. It's safe to terminate immediately.View on GitHub (pinned to 58e5313667)