pola-rs/polars · critical

integer

Error message

integer

What it means

RuntimeManager::new reads POLARS_ASYNC_THREAD_COUNT (line 19) and POLARS_MAX_BLOCKING_THREAD_COUNT, calling parse::<usize>().expect("integer"). Any value that is not a bare unsigned integer - floats, negative numbers, whitespace, empty string - panics. The manager initializes lazily on first async use, so the panic surfaces far from the env var that caused it.

Source

Thrown at crates/polars-async/src/lib.rs:19

use std::sync::{Arc, LazyLock};

use polars_error::polars_warn;
use polars_utils::relaxed_cell::RelaxedCell;
use tokio::runtime::{Builder, Runtime};

use crate::executor::{THREAD_SPAWNED_BY_POLARS_EXECUTOR, is_scheduling_polars_executor_thread};

pub mod executor;
pub mod primitives;

pub struct RuntimeManager {
    rt: Runtime,
}

impl RuntimeManager {
    fn new() -> Self {
        let n_threads = std::env::var("POLARS_ASYNC_THREAD_COUNT")
            .map(|x| x.parse::<usize>().expect("integer"))
            .unwrap_or(usize::min(polars_config::config().max_threads(), 32));

        let max_blocking = std::env::var("POLARS_MAX_BLOCKING_THREAD_COUNT")
            .map(|x| x.parse::<usize>().expect("integer"))
            .unwrap_or(512);

        if polars_config::config().verbose() {
            eprintln!("async thread count: {n_threads}");
            eprintln!("blocking thread count: {max_blocking}");
        }

        let max_total_threads = n_threads + max_blocking;
        let warned = RelaxedCell::new_bool(false);
        let tokio_thread_count_start = Arc::new(RelaxedCell::new_i64(0));
        let tokio_thread_count_stop = tokio_thread_count_start.clone();

        let rt = Builder::new_multi_thread()
            .worker_threads(n_threads)

View on GitHub (pinned to df599052da)

Solutions

  1. Fix the value to a plain decimal integer: export POLARS_ASYNC_THREAD_COUNT=8
  2. Or simply unset it - Polars then defaults to min(max_threads, 32)
  3. Audit sibling variable POLARS_MAX_BLOCKING_THREAD_COUNT, which fails identically
  4. Check for literal quotes, spaces, 'K'-suffixes, or negative signs in the env value

Example fix

# before
export POLARS_ASYNC_THREAD_COUNT="8 "   # trailing space -> parse fails

# after
export POLARS_ASYNC_THREAD_COUNT=8
Defensive patterns

Strategy: validation

Validate before calling

// Rust: verify before any async work
for var in ["POLARS_ASYNC_THREAD_COUNT", "POLARS_MAX_BLOCKING_THREAD_COUNT"] {
    if let Ok(v) = std::env::var(var) {
        assert!(v.parse::<usize>().is_ok(), "{var} must be a plain integer, got {v:?}");
    }
}

# Shell: fail fast in entrypoints
[ -z "${POLARS_ASYNC_THREAD_COUNT:-}" ] || [[ "$POLARS_ASYNC_THREAD_COUNT" =~ ^[0-9]+$ ]] \
  || { echo "POLARS_ASYNC_THREAD_COUNT must be an integer" >&2; exit 1; }

Prevention

When it happens

Trigger: First use of Polars' async runtime (cloud reads, async globbing, async engine) with POLARS_ASYNC_THREAD_COUNT set to values like '4.0', ' 4', '-1', or '' (empty interpolation).

Common situations: .env / docker-compose entries with quotes or trailing whitespace; shell scripts interpolating unset variables to empty strings; copy-pasted configs expecting float thread counts; CI injecting stray values.

Related errors


AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16). Data as JSON: /api/errors/9378a79e2fe50c6b. Report an issue: GitHub.