vectordotdev/vector · error
Failed to set up SIGHUP handler.
Error message
Failed to set up SIGHUP handler.
What it means
Vector installs async signal handlers (SIGINT, SIGTERM, SIGQUIT, SIGHUP) via tokio::signal inside a Tokio runtime. The `signal()` call returns a Result; if registering the SIGHUP handler fails at the OS level, the code panics with this expect message. This typically means the OS refused the signal-handler registration (signal.h sigaction failure).
Solutions
- Ensure the signal setup runs inside a tokio runtime (runtime.block_on as in src/signal.rs)
- Check ulimit -n and raise the file-descriptor limit
- Verify the platform supports tokio signal handling (unix targets)
- Run with elevated/unrestricted container settings if seccomp blocks signal syscalls
Example fix
// before
let mut sighup = signal(SignalKind::hangup()).expect("Failed to set up SIGHUP handler.");
// after
let mut sighup = signal(SignalKind::hangup()).map_err(|e| anyhow!("Failed to set up SIGHUP handler: {e}"))?; Defensive patterns
Strategy: fallback
Validate before calling
// rust: ensure a tokio runtime exists before registering signals assert!(tokio::runtime::Handle::try_current().is_ok(), "signal setup requires a tokio runtime"); // shell: check fd headroom ulimit -n
Type guard
fn runtime_available() -> bool { tokio::runtime::Handle::try_current().is_ok() } Try / catch
let mut sighup = signal(SignalKind::hangup()).map_err(|e| anyhow!("SIGHUP handler setup failed: {e}"))?; Prevention
- Always register signals inside a tokio runtime
- Raise the process fd limit before startup
- Test startup in containers with seccomp profiles
- Log and degrade gracefully if one signal handler fails
When it happens
Trigger: Calling the signal-registration function outside a Tokio runtime context, OS resource exhaustion (too many signal handlers/fds), or a platform where SIGHUP registration via tokio's SignalKind::hangup is unsupported.
Common situations: Embedding Vector's signal setup in a non-tokio async executor or running in restricted containers/seccomp sandboxes that block sigaction; hitting process file-descriptor limits.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Failed to set up SIGINT handler.
- Failed to set up SIGTERM handler.
- concurrent map task cancelled outside of our control
- Failed to set up SIGQUIT handler.
- should not fail to send output event
AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16).
Data as JSON: /api/errors/4f84a20afd541dd3.
Report an issue: GitHub.
Appendix: source
Thrown at src/signal.rs:200
for shutdown_tx in self.shutdown_txs.drain(..) {
// An error just means the channel was already shut down; safe to ignore.
_ = shutdown_tx.send(());
}
}
}
/// Signals from OS/user.
#[cfg(unix)]
fn os_signals(runtime: &Runtime) -> impl Stream<Item = SignalTo> + use<> {
use tokio::signal::unix::{SignalKind, signal};
// The `signal` function must be run within the context of a Tokio runtime.
runtime.block_on(async {
let mut sigint = signal(SignalKind::interrupt()).expect("Failed to set up SIGINT handler.");
let mut sigterm =
signal(SignalKind::terminate()).expect("Failed to set up SIGTERM handler.");
let mut sigquit = signal(SignalKind::quit()).expect("Failed to set up SIGQUIT handler.");
let mut sighup = signal(SignalKind::hangup()).expect("Failed to set up SIGHUP handler.");
async_stream::stream! {
loop {
let signal = tokio::select! {
_ = sigint.recv() => {
info!(message = "Signal received.", signal = "SIGINT");
SignalTo::Shutdown(None)
},
_ = sigterm.recv() => {
info!(message = "Signal received.", signal = "SIGTERM");
SignalTo::Shutdown(None)
} ,
_ = sigquit.recv() => {
info!(message = "Signal received.", signal = "SIGQUIT");
SignalTo::Quit
},
_ = sighup.recv() => {
info!(message = "Signal received.", signal = "SIGHUP");View on GitHub (pinned to bdb87aeaa4)