{"record":{"id":"eb22e800886a01c1","repo":"cloudflare/pingora","slug":"tried-to-listen-with-no-addr-specified","errorCode":null,"errorMessage":"Tried to listen with no addr specified","messagePattern":"Tried to listen with no addr specified","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pingora-core/src/listeners/l4.rs","lineNumber":338,"sourceCode":"        }\n    }\n\n    pub fn listen_addr(&mut self, addr: ServerAddress) -> &mut Self {\n        self.listen_addr = Some(addr);\n        self\n    }\n\n    #[cfg(feature = \"connection_filter\")]\n    pub fn connection_filter(&mut self, filter: Arc<dyn ConnectionFilter>) -> &mut Self {\n        self.connection_filter = Some(filter);\n        self\n    }\n\n    #[cfg(unix)]\n    pub async fn listen(self, fds: Option<ListenFds>) -> Result<ListenerEndpoint> {\n        let listen_addr = self\n            .listen_addr\n            .expect(\"Tried to listen with no addr specified\");\n\n        let listener = if let Some(fds_table) = fds {\n            let addr_str = listen_addr.as_ref();\n\n            // Acquire a per-address async lock so that only one task at a\n            // time can go through the check-bind-insert sequence for a given\n            // address. The flurry guard is dropped before the await so its\n            // !Send pointer does not cross an await point.\n            let addr_lock = {\n                let guard = BIND_LOCKS.pin();\n                match guard.get(addr_str) {\n                    Some(existing) => existing.clone(),\n                    None => {\n                        let new_lock = Arc::new(tokio::sync::Mutex::new(()));\n                        match guard.try_insert(addr_str.to_string(), new_lock.clone()) {\n                            Ok(inserted) => inserted.clone(),\n                            Err(e) => e.current.clone(),\n                        }","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/cloudflare/pingora/blob/0046038bd402bc82912da862dadf9a479f31e9f1/pingora-core/src/listeners/l4.rs#L320-L356","documentation":"The low-level listener builder (ListenerEndpoint::builder() in pingora-core/src/listeners/l4.rs) stores the address in an Option<ServerAddress> set by .listen_addr(addr). The Unix listen() implementation .expect()s it to be Some (l4.rs:338), panicking with 'Tried to listen with no addr specified' when listen() was awaited on a builder whose address was never set.","triggerScenarios":"Constructing ListenerEndpoint::builder() (or a wrapper that doesn't set the address) and calling .listen(fds).await without a prior .listen_addr(ServerAddress::Tcp(...)/Uds(...)) call.","commonSituations":"Custom transport stacks or tests using the low-level l4 listener API directly instead of the higher-level service/listener wrappers (which always set l4, see listeners/mod.rs:180); refactors that moved address setting behind a conditional that silently skipped.","solutions":["Always call .listen_addr(ServerAddress::Tcp(\"127.0.0.1:6152\".into(), None)) on the builder before .listen()","Prefer the higher-level listener/service APIs, which take the address up front and cannot reach listen() addr-less","Set the address at construction time in one helper so no code path can forget it"],"exampleFix":"// before\nlet endpoint = ListenerEndpoint::builder().listen(None).await?; // panic: no addr\n\n// after\nlet endpoint = ListenerEndpoint::builder()\n    .listen_addr(ServerAddress::Tcp(\"127.0.0.1:6152\".into(), None))\n    .listen(None)\n    .await?;","handlingStrategy":"validation","validationCode":"// Single construction point: the builder can never be addr-less\nfn tcp_listener(addr: &str) -> ListenerEndpointBuilder {\n    ListenerEndpoint::builder()\n        .listen_addr(ServerAddress::Tcp(addr.to_string().into(), None))\n        .clone()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pair ListenerEndpoint::builder() with .listen_addr() in the same expression","Prefer the higher-level listener/service APIs that take the address as a constructor argument","In tests, keep one helper that builds listeners so a forgotten address fails one place, not many"],"tags":["rust","listener","startup","pingora","panic"],"backgroundTag":"missing-listen-address","analyzedSha":"0046038bd402bc82912da862dadf9a479f31e9f1","analyzedAt":"2026-08-16T21:33:22.341Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}