{"record":{"id":"8cfc43b9ffad8644","repo":"vectordotdev/vector","slug":"systemd-fd-already-consumed-8cfc43","errorCode":null,"errorMessage":"systemd fd already consumed","messagePattern":"systemd fd already consumed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/sources/util/net/udp.rs","lineNumber":17,"sourceCode":"use std::io;\n\nuse listenfd::ListenFd;\nuse tokio::net::UdpSocket;\n\nuse super::SocketListenAddr;\n\n/// Binds a UDP socket to the listen address.\npub async fn try_bind_udp_socket(\n    addr: SocketListenAddr,\n    mut listenfd: ListenFd,\n) -> io::Result<UdpSocket> {\n    match addr {\n        SocketListenAddr::SocketAddr(addr) => UdpSocket::bind(&addr).await,\n        SocketListenAddr::SystemdFd(offset) => match listenfd.take_udp_socket(offset)? {\n            Some(socket) => UdpSocket::from_std(socket),\n            None => Err(io::Error::new(\n                io::ErrorKind::AddrInUse,\n                \"systemd fd already consumed\",\n            )),\n        },\n    }\n}\n","sourceCodeStart":1,"sourceCodeEnd":24,"githubUrl":"https://github.com/vectordotdev/vector/blob/3708c39b12a93212ed8b8d7510b4cc7769cb5864/src/sources/util/net/udp.rs#L1-L24","documentation":"Runtime error from `try_bind_udp_socket` in src/sources/util/net/udp.rs. With `SocketListenAddr::SystemdFd(offset)`, the code calls `listenfd.take_udp_socket(offset)`; a `None` result — offset beyond the inherited fds, or the fd already consumed — is returned as `io::Error` (kind `AddrInUse`, message \"systemd fd already consumed\"). UDP sockets need a matching `ListenDatagram=` systemd unit.","triggerScenarios":"A UDP source (e.g. `syslog` or `socket` with mode `udp`) configured with `address = \"systemd\"` while the systemd unit passes only `ListenStream=` (TCP) fds, passes fewer fds than the offset, the process is not systemd-supervised, or the fd was already taken by another bind.","commonSituations":"Reusing a TCP socket-activation unit for a UDP source (fd exists but is TCP, or is absent); running Vector directly during debugging while the config keeps `systemd` as the bind address.","solutions":["Declare a `ListenDatagram=` entry in the `.socket` unit for the UDP source and restart it so the fd is inherited","Match the fd offsets in Vector config to the order of systemd's passed fds; use one fd per socket","Outside systemd, bind a concrete address (`address = \"0.0.0.0:514\"`)"],"exampleFix":"# before (unit only had ListenStream=; no datagram fd)\n[sources.syslog]\ntype = \"syslog\"\naddress = \"systemd\"\nmode = \"udp\"\n\n# after\n# vector.socket: ListenDatagram=514\n[sources.syslog]\ntype = \"syslog\"\naddress = \"systemd\"\nmode = \"udp\"","handlingStrategy":"validation","validationCode":"// Before using SocketListenAddr::SystemdFd for UDP, confirm fds were inherited\nfn systemd_fd_count() -> Option<usize> {\n    let pid_ok = std::env::var(\"LISTEN_PID\").ok()?.parse::<u32>().ok()? == std::process::id();\n    let fds = std::env::var(\"LISTEN_FDS\").ok()?.parse::<usize>().ok()?;\n    pid_ok.then_some(fds)\n}","typeGuard":null,"tryCatchPattern":"match try_bind_udp_socket(addr, listenfd).await {\n    Err(e) if e.kind() == std::io::ErrorKind::AddrInUse && e.to_string().contains(\"systemd\") => {\n        // no datagram fd at that offset: fix the unit (ListenDatagram=) or bind a real address\n    }\n    other => other,\n}","preventionTips":["Declare ListenDatagram= (not ListenStream=) in the .socket unit for UDP sources","Match fd offsets to the inherited fd order; one fd per socket","Don't run systemd-bound configs outside systemd; use concrete addresses for manual runs"],"tags":["rust","systemd","socket-activation","udp","startup","vector-source"],"backgroundTag":"systemd-socket-activation-fd-missing","analyzedSha":"3708c39b12a93212ed8b8d7510b4cc7769cb5864","analyzedAt":"2026-08-20T07:02:18.786Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}