{"record":{"id":"9ac32270e996951c","repo":"jdx/mise","slug":"invalid-date-or-duration-s-expected-formats","errorCode":null,"errorMessage":"Invalid date or duration: {s}. Expected formats: '2024-06-01', '2024-06-01T12:00:00Z', '90d', '1y'","messagePattern":"Invalid date or duration: (.+?)\\. Expected formats: '2024-06-01', '2024-06-01T12:00:00Z', '90d', '1y'","errorType":"validation","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/duration.rs","lineNumber":90,"sourceCode":"        let datetime = civil_date.at(23, 59, 59, 0);\n        let ts = datetime.to_zoned(jiff::tz::TimeZone::UTC)?.timestamp();\n        return Ok(ts);\n    }\n\n    // Subtract the duration from `process_now` so the same relative\n    // duration resolves to the same absolute Timestamp every time.\n    if let Ok(span) = s.parse::<Span>() {\n        // Validate that duration is positive (negative would result in future date)\n        let duration = span.to_duration(date(2025, 1, 1))?;\n        if duration.is_negative() {\n            bail!(\"duration must not be negative: {}\", s);\n        }\n        let now_zoned = process_now().to_zoned(jiff::tz::TimeZone::UTC);\n        let past = now_zoned.checked_sub(span)?;\n        return Ok(past.timestamp());\n    }\n\n    bail!(\n        \"Invalid date or duration: {s}. Expected formats: '2024-06-01', '2024-06-01T12:00:00Z', '90d', '1y'\"\n    )\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_process_now_is_stable() {\n        let a = process_now();\n        std::thread::sleep(std::time::Duration::from_millis(5));\n        let b = process_now();\n        assert_eq!(a, b);\n    }\n\n    #[test]\n    fn test_parse_into_timestamp_relative_is_stable() {","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/duration.rs#L72-L108","documentation":"`parse_into_timestamp` (src/duration.rs:59) tries four parsers in order — RFC3339 `Timestamp`, `Zoned` datetime, `civil::Date` (YYYY-MM-DD, treated as end of day UTC), then jiff `Span`. When all four fail it bails with the list of accepted formats, so this error means the string matched no supported date or duration grammar.","triggerScenarios":"A date/duration setting receiving an unparseable string: `\"2024-13-01\"` (invalid month), `\"06/01/2024\"` (US format), `\"in 90d\"`, `\"90 days\"` in a form jiff's Span rejects, or a bare number where a span/date is required.","commonSituations":"Human-friendly strings copied from other tools' docs; locale-formatted dates; missing or doubled units (`90dd`); timezone names instead of offsets; values from CI variables that were never validated.","solutions":["Use one of the listed forms exactly: `2024-06-01`, `2024-06-01T12:00:00Z`, `90d`, `1y`","For composite relative spans use jiff span syntax without spaces/commas (e.g. `1y6m`)","Validate calendar dates (month 1-12, day valid for the month) before pasting them in"],"exampleFix":"# before\nexpiry = \"06/01/2024\"\n# after\nexpiry = \"2024-06-01\"","handlingStrategy":"validation","validationCode":"# preflight date/duration strings with the same grammar mise accepts\nimport re, sys\nok = re.fullmatch(r\"\\d{4}-\\d{2}-\\d{2}(T[\\d:]+Z?)?|\\d+[smhdwy]\", s)\nif not ok: sys.exit(f\"invalid date/duration: {s}\")","typeGuard":"fn parses_as_timestamp(s: &str) -> bool {\n    s.parse::<jiff::Timestamp>().is_ok()\n        || s.parse::<jiff::Zoned>().is_ok()\n        || s.parse::<jiff::civil::Date>().is_ok()\n        || s.parse::<jiff::Span>().is_ok()\n}","tryCatchPattern":null,"preventionTips":["Standardize on ISO dates (`2024-06-01`) and simple spans (`90d`) across your configs","Never use locale date formats (`06/01/2024`) in mise settings","Validate CI-injected date variables before they reach mise config"],"tags":["mise","date","duration","config","validation"],"backgroundTag":"invalid-date-format","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}