tokio-rs/tokio · critical
there is no signal driver running, must be called from the…
Error message
there is no signal driver running, must be called from the context of Tokio runtime
What it means
Driver::signal() calls .expect(...) when self.signal is None — the runtime has no signal driver. Signal APIs (ctrl_c, unix::signal) require the signal driver, which is only enabled with enable_all or on platforms with cfg_signal_internal_and_unix.
Solutions
- Use .enable_all() on the Builder so the signal driver is created.
- On non-Unix/non-supported targets, avoid signal APIs and handle shutdown differently.
- Ensure signal calls originate from within the runtime context (enter()/block_on).
- Verify cfg_signal_internal_and_unix is active for your target.
Example fix
// before
let rt = Builder::new_current_thread().build()?;
rt.block_on(async { signal::ctrl_c().await }); // panics
// after
let rt = Builder::new_current_thread().enable_all().build()?;
rt.block_on(async { signal::ctrl_c().await }); Defensive patterns
Strategy: validation
Validate before calling
// Ensure the signal driver is present by enabling all drivers:
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all() // includes signal driver on Unix
.build()?; Try / catch
// Panic in macro path; manual build lets you handle:
match Builder::new_current_thread().enable_all().build() {
Ok(rt) => rt.block_on(async { signal::ctrl_c().await }),
Err(e) => { eprintln!("no signal driver: {e}"); std::process::exit(1); }
} Prevention
- Use enable_all() so the signal driver runs.
- Confirm cfg_signal_internal_and_unix for your target.
- Call signal APIs only within runtime context.
When it happens
Trigger: Calling signal APIs on a runtime built without enable_io (the signal driver depends on the I/O driver) or on a platform/configuration where cfg_signal_internal_and_unix is off.
Common situations: Builder with only enable_time(); calling ctrl_c from a manually-built current-thread runtime that skipped enable_all; target without Unix signal support.
Related errors
- A Tokio 1.x context was found, but IO is disabled. Call…
- A Tokio 1.x context was found, but timers are disabled…
- signal driver gone
- background task failed
- background task failed
AI-assisted analysis of tokio-rs/tokio@8146318256 (2026-08-11).
Data as JSON: /api/errors/f79ac3d49107bd63.
Report an issue: GitHub.
Appendix: source
Thrown at tokio/src/runtime/driver.rs:105
self.io.unpark();
}
cfg_io_driver! {
#[track_caller]
pub(crate) fn io(&self) -> &crate::runtime::io::Handle {
self.io
.as_ref()
.expect("A Tokio 1.x context was found, but IO is disabled. Call `enable_io` on the runtime builder to enable IO.")
}
}
cfg_signal_internal_and_unix! {
#[track_caller]
pub(crate) fn signal(&self) -> &crate::runtime::signal::Handle {
self.signal
.as_ref()
.expect("A Tokio 1.x context was found, but IO is disabled. Call `enable_io` on the runtime builder to enable IO.")
}
}
cfg_time! {
/// Returns a reference to the time driver handle.
///
/// Panics if no time driver is present.
#[track_caller]
pub(crate) fn time(&self) -> &crate::runtime::time::Handle {
self.time
.as_ref()
.expect("A Tokio 1.x context was found, but timers are disabled. Call `enable_time` on the runtime builder to enable timers.")
}
#[cfg(tokio_unstable)]
pub(crate) fn with_time<F, R>(&self, f: F) -> R
where
F: FnOnce(Option<&crate::runtime::time::Handle>) -> R,View on GitHub (pinned to 8146318256)