{"record":{"id":"29e7bfddf0d1df3f","repo":"quickwit-oss/quickwit","slug":"err","errorCode":null,"errorMessage":"err","messagePattern":"err","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"quickwit/quickwit-serve/src/tcp_listener.rs","lineNumber":38,"sourceCode":"\n/// Resolve `SocketAddr` into `TcpListener` instances.\n///\n/// This trait can be used to inject existing [`TcpListener`] instances to the\n/// Quickwit REST and gRPC servers when running them in tests.\n#[async_trait]\npub trait TcpListenerResolver: Clone + Send + 'static {\n    async fn resolve(&self, addr: SocketAddr) -> anyhow::Result<TcpListener>;\n}\n\n#[derive(Clone)]\npub struct DefaultTcpListenerResolver;\n\n#[async_trait]\nimpl TcpListenerResolver for DefaultTcpListenerResolver {\n    async fn resolve(&self, addr: SocketAddr) -> anyhow::Result<TcpListener> {\n        TcpListener::bind(addr)\n            .await\n            .map_err(|err| anyhow::anyhow!(err))\n    }\n}\n\n#[cfg(any(test, feature = \"testsuite\"))]\npub mod for_tests {\n    use std::collections::HashMap;\n    use std::sync::Arc;\n\n    use anyhow::Context;\n    use tokio::sync::Mutex;\n\n    use super::*;\n\n    #[derive(Clone, Default)]\n    pub struct TestTcpListenerResolver {\n        listeners: Arc<Mutex<HashMap<SocketAddr, TcpListener>>>,\n    }\n","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-serve/src/tcp_listener.rs#L20-L56","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before (config)\nlisten_address: 0.0.0.0\nrest_listen_port: 7280 // already in use\n// after\nrest_listen_port: 7281","handlingStrategy":"try-catch","validationCode":"fn port_free(addr: SocketAddr) -> bool {\n    std::net::TcpListener::bind(addr).is_ok()\n}","typeGuard":null,"tryCatchPattern":"loop {\n    match server.bind(listen_addr).await {\n        Ok(srv) => break srv.serve().await,\n        Err(e) if e.to_string().contains(\"Address already in use\") => {\n            eprintln!(\"port in use, retrying in 2s...\");\n            tokio::time::sleep(Duration::from_secs(2)).await;\n        }\n        Err(e) => return Err(e.into()),\n    }\n}","preventionTips":["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"],"tags":["rust","network","tcp","server-startup"],"backgroundTag":"address-already-in-use","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}