gitbutlerapp/gitbutler · error · anyhow::Error
Failed to create tokio runtime: {err}
Error message
Failed to create tokio runtime: {err} What it means
For GitLab pipelines, but-forge spawns a thread and creates a fresh tokio runtime to run the async API call (list_pipeline_jobs_for_ref) synchronously. Runtime::new() returned Err - the process could not allocate what a runtime needs (worker threads, I/O driver, memory). The error text carries the underlying io::Error.
Source
Thrown at crates/but-forge/src/ci.rs:145
})
.collect()
})
})
}
ForgeName::GitLab => {
let preferred_account = preferred_forge_user
.as_ref()
.and_then(|user| user.gitlab().cloned());
let gl = but_gitlab::GitLabClient::from_storage(storage, preferred_account.as_ref())?;
// Clone owned data for thread
let project_id = but_gitlab::GitLabProjectId::new(owner, repo);
let reference = reference.to_string();
let reference_for_checks = reference.clone();
let pipelines = std::thread::spawn(move || -> anyhow::Result<_> {
let runtime = tokio::runtime::Runtime::new()
.map_err(|err| anyhow::anyhow!("Failed to create tokio runtime: {err}"))?;
runtime.block_on(gl.list_pipeline_jobs_for_ref(project_id, &reference))
})
.join()
.map_err(|e| anyhow::anyhow!("Failed to join thread: {e:?}"))??;
Ok(Some(
pipelines
.into_iter()
.map(|pipeline| {
let mut ci_check = CiCheck::from(pipeline);
ci_check.reference = reference_for_checks.to_string();
ci_check
})
.collect(),
))
}
ForgeName::Bitbucket => {
let preferred_account = preferred_forge_user
.as_ref()View on GitHub (pinned to caf1f223d3)
Solutions
- Raise limits for the process: `ulimit -n` (file descriptors) and thread limits, or adjust the sandbox profile
- Reduce concurrent CI lookups so fewer runtimes exist at once
- If persistent, report upstream - the long-term fix is a single shared runtime instead of per-call runtimes
Defensive patterns
Strategy: fallback
Try / catch
match list_ci_checks(&forge, owner, repo, reference) {
Err(err) if err.to_string().contains("Failed to create tokio runtime") => {
// degrade to 'CI checks unavailable'; suggest checking resource limits
}
result => result,
} Prevention
- Raise file-descriptor and thread limits for the app process (ulimit -n, sandbox profile)
- Serialize or throttle forge calls so runtime creation pressure stays low
- Track this as an upstream issue: per-call runtimes should be a single shared runtime
When it happens
Trigger: Calling CI listing for a GitLab remote when the process cannot create another runtime: thread or file-descriptor limits exhausted, or severe memory pressure.
Common situations: Desktop app sandboxes and CI containers with restrictive ulimits; many forge requests racing so each spawns its own runtime and the limit is hit.
Related errors
- Failed to join thread: {e:?}
- Failed to create runtime: {e}
- failed to create tokio runtime
- Stopped listing GitLab merge requests after unsafe paginatio
- {error_message}: {}
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/1ce012f4da3ed9bc.
Report an issue: GitHub.