gleam-lang/gleam · error

Unable to start Tokio async runtime

Error message

Unable to start Tokio async runtime

What it means

`gleam add <pkg>` (owner.rs::add) creates a multi-thread Tokio runtime to drive reqwest HTTP calls against hex.pm, and Runtime::new() must succeed (expect("Unable to start Tokio async runtime")). Runtime creation fails when the process cannot allocate the runtime's worker threads or set up its I/O driver — i.e. resource exhaustion (thread/memory limits), not anything about the package being added. The panic occurs before any network request, so credentials are never even read.

Source

Thrown at compiler-cli/src/owner.rs:12

// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2025 The Gleam contributors

use crate::{cli, http::HttpClient};
use gleam_core::{Result, hex};

pub fn add(
    package: String,
    new_owner_username_or_email: String,
    level: hexpm::OwnerLevel,
) -> Result<()> {
    let runtime = tokio::runtime::Runtime::new().expect("Unable to start Tokio async runtime");
    let http = HttpClient::new();
    let hex_config = hexpm::Config::new();
    let credentials = crate::hex::HexAuthentication::new(&runtime, &http, hex_config.clone())
        .get_or_create_api_credentials()?;

    cli::print_adding_owner();
    runtime.block_on(hex::add_owner(
        &crate::hex::write_credentials(&credentials)?,
        package,
        new_owner_username_or_email,
        level,
        &hex_config,
        &http,
    ))?;
    cli::print_added_owner();

    Ok(())
}

View on GitHub (pinned to 7e623aa83d)

Solutions

  1. Raise the process/thread limits and retry: `ulimit -u 4096` (or raise nproc limits in limits.conf), and in docker use `--pids-limit 256` or remove it.
  2. Free memory pressure (stop parallel builds, add swap) so the runtime's worker stacks can be allocated, then retry the command.
  3. If you embed this code path, build a cheaper runtime instead: tokio::runtime::Builder::new_current_thread().enable_all().build() still satisfies reqwest here.
  4. Check `dmesg`/container events for OOM or cgroup pids-max denials to confirm the resource that ran out.

Example fix

# before: container with a very low pids limit
docker run --pids-limit 16 my-gleam-ci gleam add gleam_http
# panics: Unable to start Tokio async runtime

# after: enough headroom for worker threads
docker run --pids-limit 512 my-gleam-ci gleam add gleam_http
Defensive patterns

Strategy: retry

Validate before calling

# Check thread headroom before running gleam add in CI
ulimit -u          # soft nproc limit; raise if tiny (e.g. < 512)
cat /sys/fs/cgroup/pids/current 2>/dev/null   # container usage vs pids.max
# if too low, raise limits first, then run:
ulimit -u 4096 2>/dev/null; gleam add gleam_http

Prevention

When it happens

Trigger: Running `gleam add` inside a container with a tiny pids limit (docker --pids-limit), under a low `ulimit -u`/`ulimit -v`, in a cgroup near its memory ceiling so thread stacks can't be mapped, or in a seccomp sandbox that blocks epoll/clone for the I/O driver.

Common situations: Docker/Devcontainer/Podman defaults (pids-limit=10..100), shared CI runners during heavy parallel builds, gVisor/Firecracker microVMs with restricted syscalls, systems at their global thread limit from other tooling.

Related errors


AI-assisted analysis of gleam-lang/gleam@7e623aa83d (2026-08-17). Data as JSON: /api/errors/37e9925f14eee54a. Report an issue: GitHub.