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
- Lower the --timeout value below TIMEOUT_SECS_UPPER_BOUND (check the constant's current value in quota.rs).
- Verify the unit: the flag parses durations, so use e.g. `--timeout 30s` / `30m` rather than raw large numbers.
- If the workload genuinely needs longer timeouts, raise TIMEOUT_SECS_UPPER_BOUND (and the kernel's matching limit) deliberately in code.
- 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
- Check TIMEOUT_SECS_UPPER_BOUND in quota.rs before choosing --timeout values.
- Use explicit duration units (30s, 30m) to avoid second/millisecond confusion.
- Clamp or pre-validate durations in wrapper scripts so failures happen before the IPC round trip.
- If longer timeouts are genuinely needed, raise the bound (and the kernel-side limit) in a deliberate change, not ad hoc.
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.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- durable capsule {} has malformed contracts pin
- refusing to seed canonical from a non-content-address contra
- idle timeout must be greater than 0 seconds
- idle timeout must be at most {MAX_RUN_IDLE_TIMEOUT_SECS} sec
- policy hook {event} requires a timeout from 200 to 2000 mill
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/f7b2a8328d24e7f2.
Report an issue: GitHub.