quickwit-oss/quickwit · warning

Failed to parse duration: {:?}

Error message

Failed to parse duration: {:?}

What it means

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.

Source

Thrown at quickwit/quickwit-serve/src/jaeger_api/parse_duration.rs:24

//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use prost_types::{Duration as ProstDuration, Timestamp as ProstTimestamp};

pub(crate) fn parse_duration_with_units(duration_string: String) -> anyhow::Result<ProstDuration> {
    parse_duration_nanos(&duration_string)
        .map(to_well_known_timestamp)
        .map(|timestamp| ProstDuration {
            seconds: timestamp.seconds,
            nanos: timestamp.nanos,
        })
        .map_err(|error| anyhow::anyhow!("Failed to parse duration: {:?}", error))
}

pub(crate) fn to_well_known_timestamp(timestamp_nanos: i64) -> ProstTimestamp {
    let seconds = timestamp_nanos / 1_000_000_000;
    let nanos = (timestamp_nanos % 1_000_000_000) as i32;
    ProstTimestamp { seconds, nanos }
}

/// Parses a duration string and return duration in nanoseconds.
/// A duration string is a possibly signed sequence of decimal numbers, each
/// with optional fraction and a unit suffix, such as "300ms", "-1.5h".
///
/// Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
fn parse_duration_nanos(input: &str) -> anyhow::Result<i64> {
    let mut num_str = String::new();
    for ch in input.trim().chars() {
        if ch.is_ascii_digit() || ch == '.' || ch == '-' {
            num_str.push(ch);

View on GitHub (pinned to a39730c5cd)

Solutions

  1. Correct the duration string to the supported format, e.g. `15m`, `1h`, `30s`.
  2. Read the inner debug message (wrapped in the {:?} output) to identify the exact parse failure.
  3. Reduce very large lookback durations that overflow the nanosecond i64 range.

Example fix

// before
curl '.../api/traces?lookback=2days&...'
// after
curl '.../api/traces?lookback=48h&...'
Defensive patterns

Strategy: validation

Validate before calling

fn valid_jaeger_duration(s: &str) -> bool {
    let (num, unit) = s.split_at(s.find(|c: char| !c.is_ascii_digit()).unwrap_or(s.len()));
    !num.is_empty() && matches!(unit, "us" | "ms" | "s" | "m" | "h")
}

Try / catch

match jaeger_client.find_traces(lookback).await {
    Err(e) if e.to_string().contains("Failed to parse duration") => {
        // fall back to a default lookback
        jaeger_client.find_traces("15m").await
    }
    r => r,
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.

Related errors


AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08). Data as JSON: /api/errors/854d802f8596f1ac. Report an issue: GitHub.