{"record":{"id":"854d802f8596f1ac","repo":"quickwit-oss/quickwit","slug":"failed-to-parse-duration","errorCode":null,"errorMessage":"Failed to parse duration: {:?}","messagePattern":"Failed to parse duration: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"quickwit/quickwit-serve/src/jaeger_api/parse_duration.rs","lineNumber":24,"sourceCode":"//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nuse prost_types::{Duration as ProstDuration, Timestamp as ProstTimestamp};\n\npub(crate) fn parse_duration_with_units(duration_string: String) -> anyhow::Result<ProstDuration> {\n    parse_duration_nanos(&duration_string)\n        .map(to_well_known_timestamp)\n        .map(|timestamp| ProstDuration {\n            seconds: timestamp.seconds,\n            nanos: timestamp.nanos,\n        })\n        .map_err(|error| anyhow::anyhow!(\"Failed to parse duration: {:?}\", error))\n}\n\npub(crate) fn to_well_known_timestamp(timestamp_nanos: i64) -> ProstTimestamp {\n    let seconds = timestamp_nanos / 1_000_000_000;\n    let nanos = (timestamp_nanos % 1_000_000_000) as i32;\n    ProstTimestamp { seconds, nanos }\n}\n\n/// Parses a duration string and return duration in nanoseconds.\n/// A duration string is a possibly signed sequence of decimal numbers, each\n/// with optional fraction and a unit suffix, such as \"300ms\", \"-1.5h\".\n///\n/// 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);","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-serve/src/jaeger_api/parse_duration.rs#L6-L42","documentation":"The Jaeger API endpoint parses lookback/duration query parameters like `15m` or `1h` into nanoseconds, then converts them into a protobuf duration. Any failure from parse_duration_nanos (bad format, bad unit, overflow) is wrapped in this generic error that includes the debug-formatted inner error.","triggerScenarios":"Calling Jaeger REST endpoints (e.g. /api/traces with lookback param) with a duration string that fails parsing — unknown unit suffix, non-numeric value, or value overflowing i64 nanoseconds.","commonSituations":"Jaeger UI/plugin configured with unusual lookback values; hand-written API calls with durations like `1d30m` when unsupported, or typo'd units (`15mins`, `2hours`); extremely large lookbacks exceeding nanosecond range.","solutions":["Correct the duration string to the supported format, e.g. `15m`, `1h`, `30s`.","Read the inner debug message (wrapped in the {:?} output) to identify the exact parse failure.","Reduce very large lookback durations that overflow the nanosecond i64 range."],"exampleFix":"// before\ncurl '.../api/traces?lookback=2days&...'\n// after\ncurl '.../api/traces?lookback=48h&...'","handlingStrategy":"validation","validationCode":"fn valid_jaeger_duration(s: &str) -> bool {\n    let (num, unit) = s.split_at(s.find(|c: char| !c.is_ascii_digit()).unwrap_or(s.len()));\n    !num.is_empty() && matches!(unit, \"us\" | \"ms\" | \"s\" | \"m\" | \"h\")\n}","typeGuard":null,"tryCatchPattern":"match jaeger_client.find_traces(lookback).await {\n    Err(e) if e.to_string().contains(\"Failed to parse duration\") => {\n        // fall back to a default lookback\n        jaeger_client.find_traces(\"15m\").await\n    }\n    r => r,\n}","preventionTips":["Use only supported unit suffixes (us, ms, s, m, h)","Whitelist lookback values in UIs calling the Jaeger API","Cap lookback durations to avoid nanosecond overflow"],"tags":["rust","jaeger","duration","parsing"],"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-14T16:17:12.679Z"}