astrid-runtime/astrid · error

timeout exceeds upper bound ({TIMEOUT_SECS_UPPER_BOUND}s)

Error message

timeout exceeds upper bound ({TIMEOUT_SECS_UPPER_BOUND}s)

What it means

run_set parses the --timeout duration and stores it as quotas.max_timeout_secs (floored at 1s); if the resulting seconds exceed TIMEOUT_SECS_UPPER_BOUND it bails with this error. The library enforces a kernel-side upper limit on the max timeout quota to prevent absurdly long-running workloads.

Source

Thrown at crates/astrid-cli/src/commands/quota.rs:305

    let mut client = crate::admin_client::connect_as_active_agent().await?;
    let body = client
        .request(AdminRequestKind::QuotaGet {
            principal: target.clone(),
        })
        .await?;
    let body = into_result(body)?;
    let mut quotas = match body {
        AdminResponseBody::Quotas(q) => q,
        other => anyhow::bail!("unexpected response from kernel: {other:?}"),
    };
    if let Some(s) = args.memory.as_deref() {
        quotas.max_memory_bytes = parse_bytes(s).context("invalid --memory")?;
    }
    if let Some(s) = args.timeout.as_deref() {
        let d = parse_duration(s).context("invalid --timeout")?;
        quotas.max_timeout_secs = d.as_secs().max(1);
        if quotas.max_timeout_secs > TIMEOUT_SECS_UPPER_BOUND {
            anyhow::bail!("timeout exceeds upper bound ({TIMEOUT_SECS_UPPER_BOUND}s)");
        }
    }
    if let Some(s) = args.storage.as_deref() {
        quotas.max_storage_bytes = parse_bytes(s).context("invalid --storage")?;
    }
    if let Some(n) = args.processes {
        if n > BACKGROUND_PROCESSES_UPPER_BOUND {
            anyhow::bail!("processes exceeds upper bound ({BACKGROUND_PROCESSES_UPPER_BOUND})");
        }
        quotas.max_background_processes = n;
    }
    if let Some(s) = args.ipc_rate.as_deref() {
        quotas.max_ipc_throughput_bytes = parse_bytes(s).context("invalid --ipc-rate")?;
    }
    let body = client
        .request(AdminRequestKind::QuotaSet {
            principal: target.clone(),
            quotas,

View on GitHub (pinned to affd8760f4)

Solutions

  1. Lower the --timeout value below TIMEOUT_SECS_UPPER_BOUND (check the constant's current value in quota.rs).
  2. Verify the unit: the flag parses durations, so use e.g. `--timeout 30s` / `30m` rather than raw large numbers.
  3. If the workload genuinely needs longer timeouts, raise TIMEOUT_SECS_UPPER_BOUND (and the kernel's matching limit) deliberately in code.
  4. Clamp or validate the duration in the invoking script before calling the CLI to fail early with a clearer message.

Example fix

// before
astrid quota set --principal agent-7 --timeout 48h   // bails: exceeds upper bound
// after
astrid quota set --principal agent-7 --timeout 30m   // within TIMEOUT_SECS_UPPER_BOUND
Defensive patterns

Strategy: validation

Validate before calling

// validate the requested timeout against the bound before invoking quota set
const TIMEOUT_SECS_UPPER_BOUND: u64 = 3600;
let d = humantime::parse_duration("30m")?;
let secs = d.as_secs().max(1);
if secs > TIMEOUT_SECS_UPPER_BOUND {
    anyhow::bail!("--timeout {secs}s exceeds upper bound ({TIMEOUT_SECS_UPPER_BOUND}s)");
}

Try / catch

match run_set(args).await {
    Err(e) if e.to_string().contains("timeout exceeds upper bound") => {
        eprintln!("--timeout too large; must be <= TIMEOUT_SECS_UPPER_BOUND seconds");
        ExitCode::from(2) // usage error, not runtime failure
    },
    other => other,
}

Prevention

When it happens

Trigger: Running the quota set command with --timeout whose duration, converted to whole seconds, exceeds TIMEOUT_SECS_UPPER_BOUND (e.g. `--timeout 100h` when the bound is far smaller). Only raised when --timeout is provided.

Common situations: Developer assumes durations are unbounded and passes days/hours; unit confusion (writing a large number of seconds thinking it is milliseconds, or vice versa); copying an old config where a previously legal timeout now exceeds a tightened bound.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/f7b2a8328d24e7f2. Report an issue: GitHub.