{"record":{"id":"5eb874a09968803a","repo":"quickwit-oss/quickwit","slug":"invalid-time-unit-unit","errorCode":null,"errorMessage":"Invalid time unit: {unit}","messagePattern":"Invalid time unit: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"quickwit/quickwit-serve/src/jaeger_api/parse_duration.rs","lineNumber":55,"sourceCode":"/// Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\".\nfn parse_duration_nanos(input: &str) -> anyhow::Result<i64> {\n    let mut num_str = String::new();\n    for ch in input.trim().chars() {\n        if ch.is_ascii_digit() || ch == '.' || ch == '-' {\n            num_str.push(ch);\n            continue;\n        }\n        if ch.is_alphabetic() {\n            let unit = &input[num_str.len()..];\n            let num: f64 = num_str.parse()?;\n            let duration: f64 = match unit {\n                \"ns\" => num,\n                \"us\" | \"µs\" => num * 1000.0,\n                \"ms\" => num * 1_000_000.0,\n                \"s\" => num * 1_000_000_000.0,\n                \"m\" => num * 60.0 * 1_000_000_000.0,\n                \"h\" => num * 3600.0 * 1_000_000_000.0,\n                _ => anyhow::bail!(\"Invalid time unit: {}\", unit),\n            };\n            if num < i64::MIN as f64 || num > i64::MAX as f64 {\n                anyhow::bail!(\"Invalid duration: {}\", num_str)\n            }\n            return Ok(duration.round() as i64);\n        } else {\n            anyhow::bail!(\"Invalid duration string\")\n        }\n    }\n    anyhow::bail!(\"Invalid duration string\")\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::jaeger_api::parse_duration::parse_duration_nanos;\n\n    #[test]\n    fn test_parse_duration_nanos() {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-serve/src/jaeger_api/parse_duration.rs#L37-L73","documentation":"`parse_duration_nanos` (used by the Jaeger-compatible API to convert duration strings like `\"300ms\"` into protobuf `Duration`) accepts only the unit suffixes `ns`, `us`/`µs`, `ms`, `s`, `m`, `h`. When the first non-numeric character begins a suffix not in this set (e.g. `\"5min\"`, `\"2sec\"`, `\"1H\"` — matching is case-sensitive), the matcher falls through to the `_` arm and bails. The error is then wrapped by `parse_duration_with_units` into `\"Failed to parse duration: ...\"`.","triggerScenarios":"Sending a Jaeger API request (e.g., trace lookup with `lookback=...` or span `duration` min/max parameters) whose duration string ends in an unsupported unit: `min`, `sec`, `d` (days), `w` (weeks), or uppercase variants like `5S` or `5M` (minutes vs milliseconds confusion).","commonSituations":"A Jaeger client or dashboards emitting Go-style `time.Duration` extended units (days) Quickwit doesn't support; human-written queries using `\"30min\"` instead of `\"30m\"`; copy-pasted durations from other systems using different conventions.","solutions":["Use a supported unit suffix: ns, us (or µs), ms, s, m, h — e.g. change `30min` to `30m` or `1800s`.","Convert unsupported units before sending: `2d` → `48h`, `1w` → `168h`.","Fix case: units are lowercase and case-sensitive (`5S` → `5s`, `5M` is milliseconds not minutes).","If the value comes from a client tool, configure or patch it to emit Jaeger-spec-compliant durations."],"exampleFix":"// before\nlookback=2d\n\n// after\nlookback=48h","handlingStrategy":"validation","validationCode":"const VALID: &str = \"ns|us|µs|ms|s|m|h\";\nlet re = regex::Regex::new(r\"^-?\\d+(\\.\\d+)?(ns|us|µs|ms|s|m|h)$\").unwrap();\nif !re.is_match(duration_str) {\n    return Err(format!(\"duration '{}' must match <num><unit> with units ns|us|ms|s|m|h\", duration_str));\n}","typeGuard":null,"tryCatchPattern":"match parse_duration_with_units(input) {\n    Ok(d) => use_duration(d),\n    Err(e) if e.to_string().contains(\"Invalid time unit\") => {\n        eprintln!(\"Unsupported unit in '{}'; use ns/us/ms/s/m/h\", input);\n        default_duration()\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Only emit ns/us/ms/s/m/h unit suffixes in clients targeting the Quickwit Jaeger API.","Convert day/week durations to hours before sending.","Remember units are lowercase and case-sensitive (m = minutes, ms = milliseconds).","Add a client-side regex validation for duration parameters."],"tags":["jaeger","duration-parsing","rust"],"backgroundTag":"invalid-duration-format","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}