{"record":{"id":"147759f572c96ccc","repo":"warpdotdev/warp","slug":"expiration-duration-is-too-large","errorCode":null,"errorMessage":"expiration duration is too large","messagePattern":"expiration duration is too large","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"app/src/ai/agent_sdk/api_key.rs","lineNumber":421,"sourceCode":"            } else {\n                keys.sort_by_key(|k| k.scope.clone());\n            }\n        }\n    }\n}\n\nfn expires_at_from_args(args: ApiKeyExpirationArgs) -> Result<Option<Time>> {\n    if args.no_expiration {\n        return Ok(None);\n    }\n\n    if let Some(expires_at) = args.expires_at {\n        return Ok(Some(Time::from(expires_at)));\n    }\n\n    if let Some(expires_in) = args.expires_in {\n        let duration = chrono::Duration::from_std(expires_in.into())\n            .map_err(|_| anyhow!(\"expiration duration is too large\"))?;\n        return Ok(Some(Time::from(Utc::now() + duration)));\n    }\n\n    Err(anyhow!(\"expiration behavior is required\"))\n}\n\nfn print_created_api_key(\n    result: CreatedApiKeyInfo,\n    output_format: OutputFormat,\n    json_output: warp_cli::json_filter::JsonOutput,\n) -> Result<()> {\n    if json_output.force_json_output() {\n        output::print_raw_json(serde_json::to_value(&result)?, &json_output)?;\n        return Ok(());\n    }\n    match output_format {\n        OutputFormat::Json => output::write_json(&result, std::io::stdout())?,\n        OutputFormat::Ndjson => output::write_json_line(&result, std::io::stdout())?,","sourceCodeStart":403,"sourceCodeEnd":439,"githubUrl":"https://github.com/warpdotdev/warp/blob/e72fd7aacbbb2236d9b3be2aad7e7178fe94b4bc/app/src/ai/agent_sdk/api_key.rs#L403-L439","documentation":"`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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Use `--no-expiration` for keys that should never expire","Use an absolute `--expires-at <timestamp>` instead of a relative duration","Clamp the duration to the intended real lifetime (e.g. 2160h for 90 days) before passing it"],"exampleFix":"# before\nwarp api-key create ci --expires-in 99999999999w\n# after\nwarp api-key create ci --no-expiration   # or --expires-in 2160h","handlingStrategy":"validation","validationCode":"fn expires_in_representable(d: std::time::Duration) -> bool {\n    chrono::Duration::from_std(d).is_ok()\n}\n// Map 'forever' intent to --no-expiration and clamp durations before invoking create.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Compute durations with checked arithmetic","Use --expires-at for far-future expiries","Reserve --no-expiration for no-expiry intent"],"tags":["api-key","duration","validation","cli"],"backgroundTag":null,"analyzedSha":"e72fd7aacbbb2236d9b3be2aad7e7178fe94b4bc","analyzedAt":"2026-08-16T08:27:25.381Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}