pola-rs/polars · error

integer

Error message

integer

What it means

get_semaphore initializes a global concurrency semaphore once; if POLARS_CONCURRENCY_BUDGET is set but does not parse as usize, expect("integer") panics. The whole process aborts because the budget must be a plain positive integer.

Solutions

  1. Set POLARS_CONCURRENCY_BUDGET to a plain positive integer, e.g. POLARS_CONCURRENCY_BUDGET=16.
  2. Strip whitespace/quotes from wherever the variable is exported.
  3. Unset the variable entirely to fall back to the default (rayon threads, min max-per-request).
  4. Use POLARS_MAX_THREADS instead if you wanted to control thread count rather than the semaphore budget.

Example fix

// before
POLARS_CONCURRENCY_BUDGET=12.0
// after
POLARS_CONCURRENCY_BUDGET=12
Defensive patterns

Strategy: validation

Validate before calling

if let Ok(v) = std::env::var("POLARS_CONCURRENCY_BUDGET") {
    let parsed = v.trim().parse::<usize>();
    assert!(parsed.is_ok(), "POLARS_CONCURRENCY_BUDGET must be a positive integer, got {v:?}");
}

Type guard

fn valid_budget(v: &str) -> bool { v.trim().parse::<usize>().is_ok() }

Try / catch

// expect() panics; validate the env var at process startup before any polars call
std::env::var("POLARS_CONCURRENCY_BUDGET")
    .ok()
    .filter(|v| !valid_budget(v))
    .map(|bad| panic!("fix POLARS_CONCURRENCY_BUDGET={bad:?}: must be an integer"));

Prevention

When it happens

Trigger: Setting POLARS_CONCURRENCY_BUDGET to a non-integer value (e.g. "16.0", "abc", "", "8 ", negative like "-4") before any call that reaches get_concurrency_limit, tune_with_concurrency_budget, or with_concurrency_budget.

Common situations: Setting the env var to '50%' or 'default' in CI scripts; quoting issues adding whitespace/newlines; setting it in .env files with surrounding spaces; expecting a float fraction of cores.

Understand the failure class

Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.

Related errors


AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18). Data as JSON: /api/errors/667948e08d47cfcf. Report an issue: GitHub.

Appendix: source

Thrown at crates/polars-io/src/pl_async.rs:148

                }
            },
            Optimization::Finished => {},
        }
        self.last_tune = std::time::Instant::now();
        // Not finished.
        false
    }
}
static INCR: RelaxedCell<u64> = RelaxedCell::new_u64(0);
static FINISHED_TUNING: RelaxedCell<bool> = RelaxedCell::new_bool(false);
static PERMIT_STORE: std::sync::OnceLock<tokio::sync::RwLock<SemaphoreTuner>> =
    std::sync::OnceLock::new();

fn get_semaphore() -> &'static (Semaphore, u32) {
    CONCURRENCY_BUDGET.get_or_init(|| {
        let permits = std::env::var("POLARS_CONCURRENCY_BUDGET")
            .map(|s| {
                let budget = s.parse::<usize>().expect("integer");
                FINISHED_TUNING.store(true);
                budget
            })
            .unwrap_or_else(|_| std::cmp::max(RAYON.current_num_threads(), MAX_BUDGET_PER_REQUEST));
        (Semaphore::new(permits), permits as u32)
    })
}

pub fn get_concurrency_limit() -> u32 {
    get_semaphore().1
}

pub async fn tune_with_concurrency_budget<F, Fut>(requested_budget: u32, callable: F) -> Fut::Output
where
    F: FnOnce() -> Fut,
    Fut: Future,
    Fut::Output: GetSize,
{

View on GitHub (pinned to fe841f959e)