VictoriaMetrics/VictoriaMetrics · error

cannot parse `interval: %q`: %w

Error message

cannot parse `interval: %q`: %w

What it means

The `interval` value must parse as a Go duration via time.ParseDuration (e.g. 30s, 5m, 1h). If the string is malformed, the parse error is wrapped. Bare numbers without units are the most common failure.

Source

Thrown at lib/streamaggr/streamaggr.go:479

// PushFunc is called by Aggregators when it needs to push its state to metrics storage
type PushFunc func(tss []prompb.TimeSeries)

type aggrPushFunc func([]pushSample, int64, bool)

// newAggregator creates new aggregator for the given cfg, which pushes the aggregate data to pushFunc.
//
// opts can contain additional options. If opts is nil, then default options are used.
//
// The returned aggregator must be stopped when no longer needed by calling MustStop().
func newAggregator(cfg *Config, path string, pushFunc PushFunc, ms *metrics.Set, opts *Options, alias string, aggrID int) (*aggregator, error) {
	// check cfg.Interval
	if cfg.Interval == "" {
		return nil, fmt.Errorf("missing `interval` option")
	}
	interval, err := time.ParseDuration(cfg.Interval)
	if err != nil {
		return nil, fmt.Errorf("cannot parse `interval: %q`: %w", cfg.Interval, err)
	}
	if interval < time.Second {
		return nil, fmt.Errorf("aggregation interval cannot be smaller than 1s; got %s", interval)
	}

	if opts == nil {
		opts = &Options{}
	}

	// check cfg.DedupInterval
	dedupInterval := opts.DedupInterval
	if cfg.DedupInterval != "" {
		di, err := time.ParseDuration(cfg.DedupInterval)
		if err != nil {
			return nil, fmt.Errorf("cannot parse `dedup_interval: %q`: %w", cfg.DedupInterval, err)
		}
		dedupInterval = di
	}

View on GitHub (pinned to 5079fb58f1)

Solutions

  1. Use a valid Go duration: number plus unit s/m/h, e.g. `interval: 30s`.
  2. Always include a unit; bare integers are invalid.
  3. Check the wrapped time.ParseDuration diagnostic for details.

Example fix

// before
interval: 30
// after
interval: 30s
Defensive patterns

Strategy: validation

Validate before calling

func validDuration(s string) bool {
	_, err := time.ParseDuration(s)
	return err == nil
}
// before load:
if !validDuration(cfg.Interval) {
	return fmt.Errorf("interval %q is not a Go duration like 30s", cfg.Interval)
}

Try / catch

as, err := streamaggr.LoadFromFile(path, pushFn, opts, alias)
if err != nil {
	if strings.Contains(err.Error(), "cannot parse `interval") {
		return fmt.Errorf("fix interval to a Go duration like 30s/5m: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Config entry with `interval: 30` (no unit), `interval: 30sec`, or any string Go's duration parser rejects.

Common situations: Assuming seconds is the default unit; using aliases like `min` instead of `m`; templating producing a malformed value.

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


AI-assisted analysis of VictoriaMetrics/VictoriaMetrics@5079fb58f1 (2026-09-03). Data as JSON: /api/errors/e574b6d44a31b9bb. Report an issue: GitHub.