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
- Set RCH_MINIMUM_TASK_CONCURRENCY to a plain non-negative integer (e.g. 10).
- Unset the variable to use the built-in default of 10.
- Trim whitespace/quotes from the value in the environment or process manager config.
- 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
- Set env values as bare non-negative integers with no units, quotes, or thousand separators.
- Prefer leaving the variable unset rather than guessing a value; defaults exist (10).
- Add a startup smoke test in CI that parses all RCH_* variables.
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
- Environment variable RCH_MAXIMUM_CONCURRENT_TASK_FETCH…
- Invalid port
- Invalid host
- No messages in the event
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)