{"record":{"id":"732608f9166d0092","repo":"jaegertracing/jaeger","slug":"min-start-time-is-above-max","errorCode":null,"errorMessage":"min start time is above max","messagePattern":"min start time is above max","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"internal/storage/v1/badger/spanstore/reader.go","lineNumber":31,"sourceCode":"\t\"math\"\n\t\"slices\"\n\n\t\"github.com/dgraph-io/badger/v4\"\n\t\"golang.org/x/exp/maps\"\n\n\t\"github.com/jaegertracing/jaeger-idl/model/v1\"\n\t\"github.com/jaegertracing/jaeger/internal/storage/v1/api/spanstore\"\n\t\"github.com/jaegertracing/jaeger/internal/storage/v2/api/tracestore\"\n)\n\n// Most of these errors are common with the ES and Cassandra backends. Each backend has slightly different validation rules.\n\nvar (\n\t// ErrServiceNameNotSet occurs when attempting to query with an empty service name\n\tErrServiceNameNotSet = errors.New(\"service name must be set\")\n\n\t// ErrStartTimeMinGreaterThanMax occurs when start time min is above start time max\n\tErrStartTimeMinGreaterThanMax = errors.New(\"min start time is above max\")\n\n\t// ErrDurationMinGreaterThanMax occurs when duration min is above duration max\n\tErrDurationMinGreaterThanMax = errors.New(\"min duration is above max\")\n\n\t// ErrMalformedRequestObject occurs when a request object is nil\n\tErrMalformedRequestObject = errors.New(\"malformed request object\")\n\n\t// ErrStartAndEndTimeNotSet occurs when start time and end time are not set\n\tErrStartAndEndTimeNotSet = errors.New(\"start and end time must be set\")\n\n\t// ErrUnableToFindTraceIDAggregation occurs when an aggregation query for TraceIDs fail.\n\tErrUnableToFindTraceIDAggregation = errors.New(\"could not find aggregation of traceIDs\")\n\n\t// ErrNotSupported during development, don't support every option - yet\n\tErrNotSupported = errors.New(\"this query parameter is not supported yet\")\n\n\t// ErrInternalConsistencyError indicates internal data consistency issue\n\tErrInternalConsistencyError = errors.New(\"internal data consistency issue\")","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/storage/v1/badger/spanstore/reader.go#L13-L49","documentation":"ErrStartTimeMinGreaterThanMax is returned by validateQuery when the query's StartTimeMax is before StartTimeMin, i.e. the requested time window is inverted. The badger reader builds byte-comparable timestamp keys from these bounds, so an inverted range would match nothing and is rejected up front.","triggerScenarios":"FindTraceIDs/FindTraces with TraceQueryParameters where StartTimeMax.Before(StartTimeMin) — typically from swapped arguments, a client computing min/max in the wrong order, or timezone/clock conversion mistakes.","commonSituations":"UI date pickers sending start > end; callers reversing parameter order in helper wrappers; automated scripts computing window boundaries from separate clocks with skew.","solutions":["Swap or recompute the bounds so StartTimeMin < StartTimeMax before calling.","Validate ordering client-side and reject the request early with a clear message.","If the range is legitimately empty (e.g. zero-length window), short-circuit and return an empty result without querying."],"exampleFix":"// before\nq := &spanstore.TraceQueryParameters{StartTimeMin: end, StartTimeMax: start} // inverted\nids, err := reader.FindTraceIDs(ctx, q)\n// after\nif start.After(end) {\n\tstart, end = end, start\n}\nq := &spanstore.TraceQueryParameters{StartTimeMin: start, StartTimeMax: end}\nids, err := reader.FindTraceIDs(ctx, q)","handlingStrategy":"validation","validationCode":"if q != nil && !q.StartTimeMax.IsZero() && q.StartTimeMax.Before(q.StartTimeMin) {\n\treturn errors.New(\"StartTimeMax must be after StartTimeMin\")\n}","typeGuard":"func hasValidTimeWindow(q *spanstore.TraceQueryParameters) bool {\n\treturn q != nil && !q.StartTimeMin.IsZero() && !q.StartTimeMax.IsZero() &&\n\t\tq.StartTimeMin.Before(q.StartTimeMax)\n}","tryCatchPattern":"ids, err := reader.FindTraceIDs(ctx, q)\nif errors.Is(err, spanstore.ErrStartTimeMinGreaterThanMax) {\n\treturn nil, httpError(400, \"time range is inverted: start must precede end\")\n}\nif err != nil { return nil, err }","preventionTips":["Normalize the window (swap if inverted) in one shared helper before issuing any trace search.","Use UTC consistently when computing start/end to avoid timezone-induced inversions.","Set min/max on date-range UI controls so users cannot pick an inverted range.","Unit-test time-range construction helpers with reversed inputs."],"tags":["go","badger","query-validation","time-range"],"backgroundTag":"invalid-time-range","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}