gitbutlerapp/gitbutler · error
Failed fetch review : failed to create Tokio runtime
Error message
Failed fetch review {review_number}: failed to create Tokio runtime: {e} What it means
This error wraps the failure of `tokio::runtime::Runtime::new()` when `get_forge_review` spawns a dedicated OS thread to run an async forge-review fetch via `block_on`. Tokio runtime creation can only fail in restricted environments (e.g. resource limits preventing thread or socket-pool creation), and this message surfaces that low-level cause with the review number attached. It means the review fetch never even started because no async executor could be built.
Solutions
- Check and raise the OS thread limit (ulimit -u / container pids limit) on the machine running the tool.
- Free memory or increase the memory available to the process/container.
- Retry the operation once resources are freed; the failure is environmental, not caused by the review number.
- If embedding, avoid calling from an environment with per-thread restrictions or reduce concurrent fetch operations.
Example fix
// before
let runtime = tokio::runtime::Runtime::new().map_err(|e| {
anyhow::anyhow!("Failed fetch review {review_number}: failed to create Tokio runtime: {e}")
})?;
// after: verify thread limits first, e.g. on Linux
// ulimit -u 4096 (raise the user process/thread limit)
// or in a container: --pids-limit=4096
let runtime = tokio::runtime::Runtime::new().map_err(|e| {
anyhow::anyhow!("Failed fetch review {review_number}: failed to create Tokio runtime: {e}")
})?; Defensive patterns
Strategy: try-catch
Validate before calling
// Rust: rough resource pre-check before spawning
let ok = std::thread::available_parallelism().is_ok();
if !ok { eprintln!("thread limits may block runtime creation"); } Try / catch
match get_forge_review(...) {
Ok(review) => use(review),
Err(e) if e.to_string().contains("failed to create Tokio runtime") => {
// environmental failure: raise thread limits / free memory, then retry once
}
Err(e) => return Err(e),
} Prevention
- Keep OS thread limits (ulimit -u, container pids-limit) comfortably above expected concurrency
- Avoid spawning one thread per fetch in embedded contexts; reuse a shared runtime
- Monitor memory headroom on CI runners
When it happens
Trigger: Calling `get_forge_review` on a system where `Runtime::new()` fails: the process has exhausted the ability to spawn threads (RLIMIT_NPROC / ulimit -u hit), insufficient memory for the runtime's blocking pool, or running inside a sandbox/container with restricted thread creation.
Common situations: CI containers with low thread limits; heavily loaded machines at the process/thread limit; memory-constrained environments; embedding the library in a process that already spawns many threads per operation.
Related errors
- Failed to create a runtime for the settled-review sweep
- Failed to create runtime
- failed to create tokio runtime
- Azure is unsupported at the minute. Sorry 😞.
- Branch ` ` is not part of the current workspace
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/497c567f86c7c61d.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-forge/src/review.rs:2335
}
/// Get a specific review (e.g. pull request) for a given forge repository
///
/// The resulting review will be cached.
pub fn get_forge_review(
preferred_forge_user: &Option<crate::ForgeUser>,
forge_repo_info: &crate::forge::ForgeRepoInfo,
review_number: usize,
db: &mut but_db::DbHandle,
storage: &but_forge_storage::Controller,
) -> Result<ForgeReview> {
let preferred_forge_user = preferred_forge_user.clone();
let forge_repo_info = forge_repo_info.clone();
let storage = storage.clone();
let review = std::thread::spawn(move || {
let runtime = tokio::runtime::Runtime::new().map_err(|e| {
anyhow::anyhow!(
"Failed fetch review {review_number}: failed to create Tokio runtime: {e}"
)
})?;
runtime.block_on(get_forge_review_inner(
&preferred_forge_user,
&forge_repo_info,
review_number,
&storage,
))
})
.join()
.map_err(|e| {
anyhow::anyhow!("Failed to fetch review {review_number}: thread panicked: {e:?}")
})??;
// Cache the review and ignore any issues, if any.
crate::db::upsert_review(db, &review).ok();View on GitHub (pinned to 58e5313667)