{"record":{"id":"e574b6d44a31b9bb","repo":"VictoriaMetrics/VictoriaMetrics","slug":"cannot-parse-interval-q-w","errorCode":null,"errorMessage":"cannot parse `interval: %q`: %w","messagePattern":"cannot parse `interval: %q`: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/streamaggr/streamaggr.go","lineNumber":479,"sourceCode":"\n// PushFunc is called by Aggregators when it needs to push its state to metrics storage\ntype PushFunc func(tss []prompb.TimeSeries)\n\ntype aggrPushFunc func([]pushSample, int64, bool)\n\n// newAggregator creates new aggregator for the given cfg, which pushes the aggregate data to pushFunc.\n//\n// opts can contain additional options. If opts is nil, then default options are used.\n//\n// The returned aggregator must be stopped when no longer needed by calling MustStop().\nfunc newAggregator(cfg *Config, path string, pushFunc PushFunc, ms *metrics.Set, opts *Options, alias string, aggrID int) (*aggregator, error) {\n\t// check cfg.Interval\n\tif cfg.Interval == \"\" {\n\t\treturn nil, fmt.Errorf(\"missing `interval` option\")\n\t}\n\tinterval, err := time.ParseDuration(cfg.Interval)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot parse `interval: %q`: %w\", cfg.Interval, err)\n\t}\n\tif interval < time.Second {\n\t\treturn nil, fmt.Errorf(\"aggregation interval cannot be smaller than 1s; got %s\", interval)\n\t}\n\n\tif opts == nil {\n\t\topts = &Options{}\n\t}\n\n\t// check cfg.DedupInterval\n\tdedupInterval := opts.DedupInterval\n\tif cfg.DedupInterval != \"\" {\n\t\tdi, err := time.ParseDuration(cfg.DedupInterval)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"cannot parse `dedup_interval: %q`: %w\", cfg.DedupInterval, err)\n\t\t}\n\t\tdedupInterval = di\n\t}","sourceCodeStart":461,"sourceCodeEnd":497,"githubUrl":"https://github.com/VictoriaMetrics/VictoriaMetrics/blob/5079fb58f1e8e62113f90c945ad71586c797d770/lib/streamaggr/streamaggr.go#L461-L497","documentation":"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.","triggerScenarios":"Config entry with `interval: 30` (no unit), `interval: 30sec`, or any string Go's duration parser rejects.","commonSituations":"Assuming seconds is the default unit; using aliases like `min` instead of `m`; templating producing a malformed value.","solutions":["Use a valid Go duration: number plus unit s/m/h, e.g. `interval: 30s`.","Always include a unit; bare integers are invalid.","Check the wrapped time.ParseDuration diagnostic for details."],"exampleFix":"// before\ninterval: 30\n// after\ninterval: 30s","handlingStrategy":"validation","validationCode":"func validDuration(s string) bool {\n\t_, err := time.ParseDuration(s)\n\treturn err == nil\n}\n// before load:\nif !validDuration(cfg.Interval) {\n\treturn fmt.Errorf(\"interval %q is not a Go duration like 30s\", cfg.Interval)\n}","typeGuard":null,"tryCatchPattern":"as, err := streamaggr.LoadFromFile(path, pushFn, opts, alias)\nif err != nil {\n\tif strings.Contains(err.Error(), \"cannot parse `interval\") {\n\t\treturn fmt.Errorf(\"fix interval to a Go duration like 30s/5m: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Always append a unit (s/m/h) to duration values.","Pre-validate all duration fields with time.ParseDuration before loading.","Avoid human aliases like `sec` or `min` in configs."],"tags":["config","duration-parsing","stream-aggregation"],"backgroundTag":"invalid-duration-format","analyzedSha":"5079fb58f1e8e62113f90c945ad71586c797d770","analyzedAt":"2026-09-03T18:10:26.153Z","contentChangedAt":"2026-09-03T18:10:26.153Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}