reacherhq/check-if-email-exists · critical

Environment variable RCH_MINIMUM_TASK_CONCURRENCY should…

Error message

Environment variable RCH_MINIMUM_TASK_CONCURRENCY should parse to usize

What it means

create_job_registry reads RCH_MINIMUM_TASK_CONCURRENCY from the environment and parses it as usize; if the variable is set but not a valid unsigned integer, parse() fails and expect() panics with this message. It is a startup-time configuration validation panic, not a recoverable runtime error.

Solutions

  1. Set RCH_MINIMUM_TASK_CONCURRENCY to a plain non-negative integer (e.g. 10).
  2. Unset the variable to use the built-in default of 10.
  3. Trim whitespace/quotes from the value in the environment or process manager config.
  4. Replace the expect() with proper error handling if a graceful startup failure is preferred.

Example fix

// before
var.parse::<usize>().expect("Environment variable RCH_MINIMUM_TASK_CONCURRENCY should parse to usize")
// after
var.parse::<usize>().unwrap_or_else(|_| panic!("RCH_MINIMUM_TASK_CONCURRENCY='{}' is not a valid usize", var))
Defensive patterns

Strategy: validation

Validate before calling

let min_task_conc = std::env::var("RCH_MINIMUM_TASK_CONCURRENCY")
    .map_or(Ok(10usize), |v| v.trim().parse::<usize>().map_err(|e| anyhow!("RCH_MINIMUM_TASK_CONCURRENCY={v:?} is not a valid usize: {e}")))?;

Type guard

fn parse_usize_env(name: &str) -> Result<Option<usize>, anyhow::Error> {
    match std::env::var(name) {
        Err(_) => Ok(None),
        Ok(v) => v.trim().parse::<usize>().map(Some).map_err(|e| anyhow!("{name}={v:?} is not a valid usize: {e}")),
    }
}

Try / catch

match std::env::var("RCH_MINIMUM_TASK_CONCURRENCY") {
    Ok(v) => match v.trim().parse::<usize>() {
        Ok(n) => n,
        Err(e) => { eprintln!("invalid RCH_MINIMUM_TASK_CONCURRENCY={v}: {e}"); std::process::exit(1); }
    },
    Err(_) => 10,
}

Prevention

When it happens

Trigger: RCH_MINIMUM_TASK_CONCURRENCY is exported with a non-numeric, negative (e.g. "-1"), or overflowing value when create_job_registry initializes the bulk-email-verification job registry.

Common situations: Ops staff setting the variable with a unit suffix ("10m"), quotes/whitespace, or a negative number; value set in a CI/CD secrets store as a placeholder string like "SET_ME".

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 reacherhq/check-if-email-exists@81da93e8a4 (2026-09-11). Data as JSON: /api/errors/505eee3ab34fdebd. Report an issue: GitHub.

Appendix: source

Thrown at backend/src/http/v0/bulk/mod.rs:37

pub mod get;
pub mod post;
pub mod results;
mod task;

use std::env;

use check_if_email_exists::LOG_TARGET;
use sqlx::{Pool, Postgres};
use sqlxmq::{JobRegistry, JobRunnerHandle};
use tracing::info;

pub use task::email_verification_task;

/// Create a job registry with one task: the email verification task.
pub async fn create_job_registry(pool: &Pool<Postgres>) -> Result<JobRunnerHandle, sqlx::Error> {
	let min_task_conc = env::var("RCH_MINIMUM_TASK_CONCURRENCY").map_or(10, |var| {
		var.parse::<usize>()
			.expect("Environment variable RCH_MINIMUM_TASK_CONCURRENCY should parse to usize")
	});
	let max_conc_task_fetch = env::var("RCH_MAXIMUM_CONCURRENT_TASK_FETCH").map_or(20, |var| {
		var.parse::<usize>()
			.expect("Environment variable RCH_MAXIMUM_CONCURRENT_TASK_FETCH should parse to usize")
	});

	// registry needs to be given list of jobs it can accept
	let registry = JobRegistry::new(&[email_verification_task]);

	// create runner for the message queue associated
	// with this job registry
	let registry = registry
		// Create a job runner using the connection pool.
		.runner(pool)
		// Here is where you can configure the job runner
		// Aim to keep 10-20 jobs running at a time.
		.set_concurrency(min_task_conc, max_conc_task_fetch)
		// Start the job runner in the background.

View on GitHub (pinned to 81da93e8a4)