jaegertracing/jaeger · error

unable to parse param '%s': %w

Error message

unable to parse param '%s': %w

What it means

newParseError is the single wrapping helper all query-parameter parsers (latencies, parseMetricsQueryParams, parseTime, parseDuration, parseBool, parseSpanKinds) use to annotate a parse failure with the parameter name, producing "unable to parse param '%s': %w". It tells the API caller exactly which query parameter was malformed and why. It is a message-structuring error, always caused by a lower-level parse failure.

Source

Thrown at cmd/jaeger/internal/extension/jaegerquery/internal/query_parser.go:226

		return defaultSpanKinds, newParseError(err, paramName)
	}
	return otelSpanKinds, nil
}

func mapSpanKindsToOpenTelemetry(spanKinds []string) ([]string, error) {
	otelSpanKinds := make([]string, len(spanKinds))
	for i, spanKind := range spanKinds {
		v := jptrace.StringToProtoSpanKind(spanKind)
		if v == "" {
			return otelSpanKinds, fmt.Errorf("unsupported span kind: '%s'", spanKind)
		}
		otelSpanKinds[i] = v
	}
	return otelSpanKinds, nil
}

func newParseError(err error, paramName string) error {
	return fmt.Errorf("unable to parse param '%s': %w", paramName, err)
}

View on GitHub (pinned to 806f444784)

Solutions

  1. Read the wrapped cause after the parameter name to see the exact parse failure and correct the value.
  2. For times use RFC3339/UTC format; for durations use Go-style units (e.g. 1h30m); for booleans use true/false; for span kinds use the accepted OTel strings.
  3. Validate query parameters client-side before building the request.
  4. URL-encode values so stray characters do not corrupt parsing.

Example fix

// before
GET /api/traces?start=2024-01-01 10:00&end=never

// after
GET /api/traces?start=2024-01-01T10%3A00%3A00Z&end=2024-01-01T11%3A00%3A00Z&lookback=1h
Defensive patterns

Strategy: validation

Validate before calling

func validateParams(p url.Values) error {
    if v := p.Get("start"); v != "" {
        if _, err := time.Parse(time.RFC3339, v); err != nil {
            return fmt.Errorf("start must be RFC3339: %w", err)
        }
    }
    if v := p.Get("lookback"); v != "" {
        if _, err := time.ParseDuration(v); err != nil {
            return fmt.Errorf("lookback must be a Go duration: %w", err)
        }
    }
    return nil
}

Type guard

func isRFC3339(s string) bool {
    _, err := time.Parse(time.RFC3339, s)
    return err == nil
}

Try / catch

mq, err := parseMetricsQueryParams(r.URL.Query())
if err != nil {
    // err is 'unable to parse param <name>: <cause>'
    http.Error(w, err.Error(), http.StatusBadRequest)
    return
}

Prevention

When it happens

Trigger: Any Jaeger query extension HTTP query where a parameter fails its parser: non-numeric latency values, timestamps outside RFC3339 for parseTime, invalid duration strings for parseDuration, non-boolean values for parseBool, or an unsupported span kind from mapSpanKindsToOpenTelemetry (error 211) wrapped with the param name.

Common situations: Hand-written client requests with ?start=2024-13-45 (invalid date), ?lookback=fortnight (invalid duration), ? SpanKind casing issues, or SDK clients whose time format changed between versions.

Understand the failure class

Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.

Related errors


AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01). Data as JSON: /api/errors/a7d95b7c331952b0. Report an issue: GitHub.