vectordotdev/vector · error
systemd fd already consumed
Error message
systemd fd already consumed
What it means
Runtime error from `build_ts_tcp_listener` in src/sources/util/net/tcp/mod.rs. When a socket address is `SocketListenAddr::SystemdFd(offset)`, Vector asks `listenfd` (the systemd socket-activation fds) for the listener at that offset. `take_tcp_listener` returning `None` means no TCP listener exists at that offset — the fd index is out of range or the fd was already taken — and Vector surfaces it as `io::Error` (kind `AddrInUse`, message "systemd fd already consumed").
Source
Thrown at src/sources/util/net/tcp/mod.rs:68
pub async fn try_bind_tcp_listener(
addr: SocketListenAddr,
mut listenfd: ListenFd,
tls: &MaybeTlsSettings,
tls_reloader: Option<TlsAcceptorReloader>,
allowlist: Option<Vec<IpNet>>,
) -> crate::Result<MaybeTlsListener> {
match addr {
SocketListenAddr::SocketAddr(addr) => tls
.bind_reloadable(&addr, tls_reloader)
.await
.map_err(Into::into),
SocketListenAddr::SystemdFd(offset) => match listenfd.take_tcp_listener(offset)? {
Some(listener) => TcpListener::from_std(listener)
.map(Into::into)
.map_err(Into::into),
None => {
Err(io::Error::new(io::ErrorKind::AddrInUse, "systemd fd already consumed").into())
}
},
}
.map(|listener| listener.with_allowlist(allowlist))
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum TcpSourceAck {
Ack,
Error,
Reject,
}
pub trait TcpSourceAcker {
fn build_ack(self, ack: TcpSourceAck) -> Option<Bytes>;
}
pub struct TcpNullAcker;View on GitHub (pinned to 3708c39b12)
Solutions
- Run Vector under systemd with the socket unit started so the fds are actually inherited (`systemctl start vector.socket vector.service`)
- Align the number and order of `ListenStream=` entries with the configured fd offsets (fd 3 = offset 0, fd 4 = offset 1, ...)
- Ensure each configured listener uses a distinct fd — an fd can only be taken once; check reload paths that rebind
- When not using socket activation, bind a concrete address (`address = "0.0.0.0:9000"`) instead of `systemd`
Example fix
# before [sources.in] type = "socket" address = "systemd" # fails when run outside systemd # after (manual/dev run) [sources.in] type = "socket" address = "0.0.0.0:9000"
Defensive patterns
Strategy: validation
Validate before calling
// Before using SocketListenAddr::SystemdFd(offset), confirm fds were inherited
fn systemd_fd_count() -> Option<usize> {
let pid_ok = std::env::var("LISTEN_PID").ok()?.parse::<u32>().ok()? == std::process::id();
let fds = std::env::var("LISTEN_FDS").ok()?.parse::<usize>().ok()?;
pid_ok.then_some(fds)
}
// use: systemd_fd_count().is_some_and(|n| n > offset) Try / catch
match build_tcp_listener(addr, listenfd, tls, reloader).await {
Err(e) if e.to_string().contains("systemd fd already consumed") => {
// fd offset out of range or already taken: fix the .socket unit / offsets, don't retry
}
other => other,
} Prevention
- Run Vector under systemd with the .socket unit started when binding to "systemd"
- Keep ListenStream= entries in the unit in exact 1:1 order with configured fd offsets (offset 0 = fd 3)
- Use a distinct fd per listener; never re-take an fd across reloads
- When debugging outside systemd, temporarily bind a concrete host:port
When it happens
Trigger: Configuring `address = "systemd"` / `use_systemd_fd = N` while: running Vector outside systemd (no `LISTEN_FDS` passed), the systemd socket unit passing fewer fds than the configured offset (offsets are 0-based over the inherited fds), a second listener re-taking an fd already consumed (e.g. after config reload rebinding), or the systemd unit not actually enabled for socket activation.
Common situations: Debugging a systemd-socket-activated Vector manually (foreground, no systemd) while the config still points at inherited fds; `.socket` units whose `ListenStream=` entries don't line up 1:1 with the Vector sources' fd offsets.
Related errors
- systemd fd already consumed
- NotConnected
- Failed to set up SIGINT handler.
- invalid timestamp
- path and query should never fail to parse
AI-assisted analysis of vectordotdev/vector@3708c39b12 (2026-08-20).
Data as JSON: /api/errors/b3305dbc5441aa01.
Report an issue: GitHub.