vectordotdev/vector · error

Failed to set up SIGQUIT handler.

Error message

Failed to set up SIGQUIT handler.

What it means

The Unix signal handler registers tokio's `signal` streams for SIGINT, SIGTERM, SIGQUIT, and SIGHUP inside a dedicated runtime. Each registration is asserted; failing to install the SIGQUIT handler panics with "Failed to set up SIGQUIT handler.". Registration fails when signal handling cannot be set up at the OS level.

Solutions

  1. Ensure the signal setup is invoked from within an active Tokio runtime (the wrapper already uses block_on — do not call it from a torn-down runtime).
  2. Check the container seccomp/apparmor profile permits `rt_sigaction`/signalfd syscalls.
  3. Verify the platform supports tokio's signal driver (Unix only path) and that signal handlers aren't exhausted.

Example fix

// before
tokio::runtime::Runtime::new().unwrap().shutdown_timeout(Duration::from_secs(0));
signal_handler(); // panics: runtime gone
// after
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(signal_handler()); // register while runtime is live
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure we are inside a runtime before installing handlers:
assert!(tokio::runtime::Handle::try_current().is_ok(), "signal setup requires an active tokio runtime");

Try / catch

match tokio::signal::unix::signal(tokio::signal::unix::SignalKind::quit()) {
    Ok(rx) => { /* proceed */ }
    Err(e) => { eprintln!("SIGQUIT handler unavailable: {e}; falling back to default termination"); }
}

Prevention

When it happens

Trigger: Calling the signal setup function outside a Tokio runtime context or where the runtime has been shut down, or when the OS refuses to install the handler (signal mask/rlimit issues, unsupported platform).

Common situations: Running vector in minimal containers where signal syscalls are blocked by seccomp profiles; calling the signal machinery from a non-async context; ephemeral runtimes torn down before registration.

Related errors


AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16). Data as JSON: /api/errors/ea0e3d6b352c556c. Report an issue: GitHub.

Appendix: source

Thrown at src/signal.rs:199

    pub fn clear(&mut self) {
        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() => {

View on GitHub (pinned to bdb87aeaa4)