BloopAI/vibe-kanban · critical
failed to build global Tokio runtime
Error message
failed to build global Tokio runtime
What it means
rt() builds a process-global Tokio multi-thread runtime inside a OnceLock and panics with expect("failed to build global Tokio runtime") if tokio::runtime::Builder::build() fails. build() essentially only fails when the runtime configuration is invalid (e.g. worker counts below the minimum or a bug in runtime options), or in constrained environments where OS resources (threads) cannot be allocated. Because the result is cached in a OnceLock, any panic here poisons the first call to block_on and every subsequent sync-to-async bridge call.
Source
Thrown at crates/utils/src/tokio.rs:11
use std::{future::Future, sync::OnceLock};
use tokio::runtime::{Builder, Handle, Runtime, RuntimeFlavor};
fn rt() -> &'static Runtime {
static RT: OnceLock<Runtime> = OnceLock::new();
RT.get_or_init(|| {
Builder::new_multi_thread()
.enable_all()
.build()
.expect("failed to build global Tokio runtime")
})
}
/// Run an async future from sync code safely.
/// If already inside a Tokio runtime, it will use that runtime.
pub fn block_on<F, T>(fut: F) -> T
where
F: Future<Output = T> + Send,
T: Send,
{
match Handle::try_current() {
// Already inside a Tokio runtime
Ok(h) => match h.runtime_flavor() {
// Use block_in_place so other tasks keep running.
RuntimeFlavor::MultiThread => tokio::task::block_in_place(|| rt().block_on(fut)),
// Spawn a new thread to avoid freezing a single-thread runtime.
RuntimeFlavor::CurrentThread | _ => std::thread::scope(|s| {
s.spawn(|| rt().block_on(fut))View on GitHub (pinned to 4deb7eca8f)
Solutions
- Check ulimit -u / RLIMIT_NPROC and raise the thread/process limit if it is exhausted.
- Ensure the process isn't memory-starved; free memory or increase container limits.
- If embedding in a runtime-restricted host, provide your own runtime and call runtime.block_on directly instead of going through block_on().
- Refactor rt() to return Result<&'static Runtime, tokio::io::Error> (or use get_or_try_init) so the error is reported instead of panicking.
Example fix
// before
RT.get_or_init(|| {
Builder::new_multi_thread()
.enable_all()
.build()
.expect("failed to build global Tokio runtime")
})
// after
RT.get_or_try_init(|| {
Builder::new_multi_thread()
.enable_all()
.build()
}).map_err(|e| anyhow::anyhow!("failed to build global Tokio runtime: {e}"))? Defensive patterns
Strategy: try-catch
Validate before calling
// sanity-check the process can spawn threads before bridging into async
use std::thread;
match thread::Builder::new().name("probe").spawn(|| {}) {
Ok(h) => { let _ = h.join(); }
Err(e) => eprintln!("cannot create threads (check ulimit -u / RLIMIT_NPROC): {e}"),
} Try / catch
let out = std::panic::catch_unwind(|| vibe_utils::block_on(future))
.map_err(|_| anyhow::anyhow!("global tokio runtime failed to build (check thread limits)"))?; Prevention
- Raise RLIMIT_NPROC/ulimit -u in sandboxed or heavily constrained environments.
- Avoid running the library inside hosts that forbid thread creation (strict seccomp, single-thread sandboxes).
- If your app already owns a Tokio runtime, call runtime.block_on directly instead of the global block_on().
- Monitor memory and thread counts; runtime construction fails under resource exhaustion.
When it happens
Trigger: Calling block_on() (the only caller of rt()) in a process where Builder::new_multi_thread().enable_all().build() returns Err — practically: extreme thread-creation failures (rlimit/ulimit on threads/processes exhausted), or exotic platforms where multi-thread runtime construction is unsupported.
Common situations: Embedding the library in a process with nproc/thread rlimits set to 1; sandboxed environments (some CI sandboxes, WASM-adjacent or seccomp-restricted setups) that forbid thread creation; memory exhaustion during runtime spawn.
Related errors
- Default profiles v3 JSON is invalid
- request_id called for unsupported request variant
- handled non-session commands earlier
- Raw stream should only have Stdout/Stderr/Finished
- Copy files task failed: {e}
AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29).
Data as JSON: /api/errors/554234ed9de1ae43.
Report an issue: GitHub.