jaegertracing/jaeger · error
file must begin with '['
Error message
file must begin with '['
What it means
lengthOfTime reads a constant that must represent a duration and parses it via expression.ReadConstant with FieldTypeDuration. When the constant's text is not a valid duration string (e.g. "2s", "100ms"), ReadConstant fails and the filter is rejected as invalid, wrapping tracestore.ErrFilterInvalid so callers can detect it with errors.Is. This happens when a duration comparison (e.g. duration > X) is built from a tree whose constant was not finalized into a DurationValue.
Source
Thrown at cmd/anonymizer/app/uiconv/reader.go:57
capturedFile: cf,
reader: bufio.NewReader(cf),
}, nil
}
// NextSpan reads the next span from the capture file, or returns errNoMoreSpans.
func (r *spanReader) NextSpan() (*uimodel.Span, error) {
if r.eofReached {
return nil, errNoMoreSpans
}
if r.spansRead == 0 {
b, err := r.reader.ReadByte()
if err != nil {
r.eofReached = true
return nil, fmt.Errorf("cannot read file: %w", err)
}
if b != '[' {
r.eofReached = true
return nil, errors.New("file must begin with '['")
}
}
s, err := r.reader.ReadString('\n')
if err != nil {
r.eofReached = true
return nil, fmt.Errorf("cannot read file: %w", err)
}
if s[len(s)-2] == ',' { // all but last span lines end with ,\n
s = s[0 : len(s)-2]
} else {
r.eofReached = true
}
var span uimodel.Span
err = json.Unmarshal([]byte(s), &span)
if err != nil {
r.eofReached = true
return nil, fmt.Errorf("cannot unmarshal span: %w; %s", err, s)
}View on GitHub (pinned to 806f444784)
Solutions
- Write the duration constant as a valid Go-style duration string with a unit, e.g. "2s", "100ms", "1h".
- Ensure the expression tree is finalized before filtering so typed constants become expression.DurationValue instead of raw untyped constants.
- Check the wrapped inner error (errors.Is/As on ErrFilterInvalid) to surface the parse failure message to the end user.
Example fix
// before
{"duration": {"gt": "2sec"}}
// after
{"duration": {"gt": "2s"}} Defensive patterns
Strategy: validation
Validate before calling
func validDuration(s string) bool {
_, err := time.ParseDuration(s)
return err == nil
}
// check before submitting: validDuration("2s") Type guard
func asDuration(e expression.Expression) (*expression.DurationValue, bool) {
d, ok := e.(*expression.DurationValue)
return d, ok
} Try / catch
q, err := buildFilterQuery(...)
if errors.Is(err, tracestore.ErrFilterInvalid) {
// surface parse message to user, fix duration syntax like "2s"
} Prevention
- Always include a unit in duration literals: 2s, 100ms, 1h.
- Run expression finalization before filtering so constants become DurationValue.
- Unit-test duration filters with ParseDuration-valid strings.
When it happens
Trigger: Calling a trace search whose filter compares the duration field against a constant written in an unrecognized format, e.g. duration > "two seconds" or duration >= "5" without a unit; the constant reaches lengthOfTime via buildDurationComparison without having been finalized into a DurationValue.
Common situations: Typing a duration filter without a time unit in a query UI or API request; writing durations in human phrasing ("2 seconds") instead of Go-style duration syntax; a query built programmatically without running finalization on the expression tree.
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
- empty configuration
- at least one storage backend is required
- cannot assign unique span ID, too many spans in the trace
- max spans count reached
- only one of basic auth (--es.username/--es.password), --es.t
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/c463dc9e05d325c9.
Report an issue: GitHub.