tsenart/vegeta · error
timeseries: non monotonically increasing timestamp
Error message
timeseries: non monotonically increasing timestamp
What it means
errMonotonicTimestamp is returned by timeSeries.add when a sample's timestamp is smaller than the previously recorded one. The plotting time series requires strictly forward-moving timestamps to keep buckets ordered.
Source
Thrown at lib/plot/timeseries.go:29
// An in-memory timeSeries of points with high compression of
// both timestamps and values. It's not safe for concurrent use.
type timeSeries struct {
attack string
label string
prev uint64
data *tsz.Series
len int
}
func newTimeSeries(attack, label string) *timeSeries {
return &timeSeries{
attack: attack,
label: label,
data: tsz.New(0),
}
}
var errMonotonicTimestamp = errors.New("timeseries: non monotonically increasing timestamp")
func (ts *timeSeries) add(t uint64, v float64) error {
if ts.prev > t {
return errMonotonicTimestamp
}
ts.data.Push(t, v)
ts.prev = t
ts.len++
return nil
}
func (ts *timeSeries) iter() lttb.Iter {
it := ts.data.Iter()
return func(count int) ([]lttb.Point, error) {
ps := make([]lttb.Point, 0, count)
for i := 0; i < count && it.Next(); i++ {View on GitHub (pinned to cf58112690)
Solutions
- Sort results by timestamp before feeding them into the plot/report builder.
- Ensure timestamps come from a single monotonic source (e.g. time.Since(start) rather than wall clock).
- If merging series, merge in sorted order or skip/drop out-of-order samples.
Example fix
// before
for _, r := range results { ts.add(uint64(r.Timestamp.UnixNano()), 1) }
// after
sort.Slice(results, func(i, j int) bool { return results[i].Timestamp.Before(results[j].Timestamp) })
for _, r := range results { ts.add(uint64(r.Timestamp.UnixNano()), 1) } Defensive patterns
Strategy: validation
Validate before calling
sort.Slice(results, func(i, j int) bool {
return results[i].Timestamp.Before(results[j].Timestamp)
}) Try / catch
if err := ts.add(uint64(r.Timestamp.UnixNano()), v); err != nil {
log.Printf("skipping out-of-order sample: %v", err)
continue
} Prevention
- Sort results by Timestamp before plotting/reporting
- Use monotonic clock deltas instead of wall-clock times
- Sequence timestamps when merging multiple attack outputs
When it happens
Trigger: Calling add(t, v) on lib/plot's timeSeries with t < ts.prev — e.g. replaying out-of-order results or feeding unsorted result slices into the plotting/reporting path.
Common situations: Sorting results by the wrong field, multiple concurrent attackers writing to one time series without ordering, or clock changes producing non-increasing uint64 nanosecond timestamps.
Related errors
AI-assisted analysis of tsenart/vegeta@cf58112690 (2026-08-31).
Data as JSON: /api/errors/bfa06b406aa81f18.
Report an issue: GitHub.