quickwit-oss/quickwit · critical
err
Error message
err
What it means
Quickwit's server startup binds its TCP listener through the TcpListenerResolver abstraction. The default resolver wraps the std Tokio bind result, converting any bind failure (address in use, permission denied, invalid address) into an anyhow error. The message is just `err`, so the underlying OS error text carries the real cause.
Solutions
- Check what occupies the port (ss -ltnp / lsof -i :PORT) and stop it or choose another port.
- Change the listen_address port in the Quickwit node config or via the --listen-address CLI flag.
- If binding a privileged port, run with the required capability or use a high port behind a proxy.
- Verify the configured address is assigned to the machine (avoid hardcoded external IPs inside containers).
Example fix
// before (config) listen_address: 0.0.0.0 rest_listen_port: 7280 // already in use // after rest_listen_port: 7281
Defensive patterns
Strategy: try-catch
Validate before calling
fn port_free(addr: SocketAddr) -> bool {
std::net::TcpListener::bind(addr).is_ok()
} Try / catch
loop {
match server.bind(listen_addr).await {
Ok(srv) => break srv.serve().await,
Err(e) if e.to_string().contains("Address already in use") => {
eprintln!("port in use, retrying in 2s...");
tokio::time::sleep(Duration::from_secs(2)).await;
}
Err(e) => return Err(e.into()),
}
} Prevention
- Pick high, uncommon ports (e.g. 7280/7281) and check for conflicts at deploy time
- In containers, avoid ports <1024 or grant CAP_NET_BIND_SERVICE
- Use bind 0.0.0.0 or an address actually assigned to the host
- Verify port availability in startup/health scripts before launching
When it happens
Trigger: Starting the Quickwit server (rest/grpc listen address) when TcpListener::bind fails: port already occupied, binding to a privileged port without permissions, or binding to an address not assigned to the host.
Common situations: Another Quickwit instance or different service already listening on the port; Docker/Kubernetes port conflicts; running in a container without CAP_NET_BIND_SERVICE while binding port <1024; typo'd listen_address in config.
Related errors
- 1 is always non-zero.
- 60 should be non-zero
- ack_id not found in in-flight
- `append_records` should be called with `position_opt: None`
- `assign_jobs` should return at least one client or fail.
AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08).
Data as JSON: /api/errors/29e7bfddf0d1df3f.
Report an issue: GitHub.
Appendix: source
Thrown at quickwit/quickwit-serve/src/tcp_listener.rs:38
/// Resolve `SocketAddr` into `TcpListener` instances.
///
/// This trait can be used to inject existing [`TcpListener`] instances to the
/// Quickwit REST and gRPC servers when running them in tests.
#[async_trait]
pub trait TcpListenerResolver: Clone + Send + 'static {
async fn resolve(&self, addr: SocketAddr) -> anyhow::Result<TcpListener>;
}
#[derive(Clone)]
pub struct DefaultTcpListenerResolver;
#[async_trait]
impl TcpListenerResolver for DefaultTcpListenerResolver {
async fn resolve(&self, addr: SocketAddr) -> anyhow::Result<TcpListener> {
TcpListener::bind(addr)
.await
.map_err(|err| anyhow::anyhow!(err))
}
}
#[cfg(any(test, feature = "testsuite"))]
pub mod for_tests {
use std::collections::HashMap;
use std::sync::Arc;
use anyhow::Context;
use tokio::sync::Mutex;
use super::*;
#[derive(Clone, Default)]
pub struct TestTcpListenerResolver {
listeners: Arc<Mutex<HashMap<SocketAddr, TcpListener>>>,
}
View on GitHub (pinned to a39730c5cd)