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

  1. Raise limits for the process: `ulimit -n` (file descriptors) and thread limits, or adjust the sandbox profile
  2. Reduce concurrent CI lookups so fewer runtimes exist at once
  3. 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

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


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/1ce012f4da3ed9bc. Report an issue: GitHub.