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
- Read the wrapped cause after the parameter name to see the exact parse failure and correct the value.
- 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.
- Validate query parameters client-side before building the request.
- 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
- Build queries via the official Jaeger client libraries rather than string concatenation.
- Use RFC3339 for timestamps and Go duration strings (1h, 30m) for lookback windows.
- URL-encode all parameter values.
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.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- %s and %s are required
- %s must be before %s
- tools[%d].name is empty or whitespace
- unsupported span kind: '%s'
- trace_id is required
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/a7d95b7c331952b0.
Report an issue: GitHub.