warpdotdev/warp · error · anyhow::Error

expiration duration is too large

Error message

expiration duration is too large

What it means

`expires_at_from_args` converts the `--expires-in` duration into a chrono Duration before adding it to Utc::now(). `chrono::Duration::from_std` fails when the value exceeds chrono's representable range, so the request is rejected as too large instead of overflowing the expiry timestamp.

Source

Thrown at app/src/ai/agent_sdk/api_key.rs:421

            } else {
                keys.sort_by_key(|k| k.scope.clone());
            }
        }
    }
}

fn expires_at_from_args(args: ApiKeyExpirationArgs) -> Result<Option<Time>> {
    if args.no_expiration {
        return Ok(None);
    }

    if let Some(expires_at) = args.expires_at {
        return Ok(Some(Time::from(expires_at)));
    }

    if let Some(expires_in) = args.expires_in {
        let duration = chrono::Duration::from_std(expires_in.into())
            .map_err(|_| anyhow!("expiration duration is too large"))?;
        return Ok(Some(Time::from(Utc::now() + duration)));
    }

    Err(anyhow!("expiration behavior is required"))
}

fn print_created_api_key(
    result: CreatedApiKeyInfo,
    output_format: OutputFormat,
    json_output: warp_cli::json_filter::JsonOutput,
) -> Result<()> {
    if json_output.force_json_output() {
        output::print_raw_json(serde_json::to_value(&result)?, &json_output)?;
        return Ok(());
    }
    match output_format {
        OutputFormat::Json => output::write_json(&result, std::io::stdout())?,
        OutputFormat::Ndjson => output::write_json_line(&result, std::io::stdout())?,

View on GitHub (pinned to e72fd7aacb)

Solutions

  1. Use `--no-expiration` for keys that should never expire
  2. Use an absolute `--expires-at <timestamp>` instead of a relative duration
  3. Clamp the duration to the intended real lifetime (e.g. 2160h for 90 days) before passing it

Example fix

# before
warp api-key create ci --expires-in 99999999999w
# after
warp api-key create ci --no-expiration   # or --expires-in 2160h
Defensive patterns

Strategy: validation

Validate before calling

fn expires_in_representable(d: std::time::Duration) -> bool {
    chrono::Duration::from_std(d).is_ok()
}
// Map 'forever' intent to --no-expiration and clamp durations before invoking create.

Prevention

When it happens

Trigger: Creating an API key with `--expires-in <duration>` whose total magnitude overflows chrono::Duration (values near u64::MAX seconds, or hum/CLI values that parse to absurd magnitudes).

Common situations: Scripts computing --expires-in with overflowing arithmetic; users expressing 'never expires' as a huge number instead of --no-expiration; unit mixups (weeks vs seconds) producing absurd values.

Related errors


AI-assisted analysis of warpdotdev/warp@e72fd7aacb (2026-08-16). Data as JSON: /api/errors/147759f572c96ccc. Report an issue: GitHub.