mikefarah/yq · error
unable to parse duration [%v]: %w
Error message
unable to parse duration [%v]: %w
What it means
When subtracting from a datetime, the RIGHT operand must be a Go-parsable duration string (e.g. `1h30m`, `-300ms`). yq negates it and calls time.ParseDuration; if the string isn't a valid Go duration, this wrapped error is returned showing the offending value and the underlying parse error.
Source
Thrown at pkg/yqlib/operator_subtract.go:143
target.Value = fmt.Sprintf("%v", result)
} else {
return fmt.Errorf("%v cannot be added to %v", lhs.Tag, rhs.Tag)
}
return nil
}
func subtractDateTime(layout string, target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {
var durationStr string
if strings.HasPrefix(rhs.Value, "-") {
durationStr = rhs.Value[1:]
} else {
durationStr = "-" + rhs.Value
}
duration, err := time.ParseDuration(durationStr)
if err != nil {
return fmt.Errorf("unable to parse duration [%v]: %w", rhs.Value, err)
}
currentTime, err := parseDateTime(layout, lhs.Value)
if err != nil {
return err
}
newTime := currentTime.Add(duration)
target.Value = newTime.Format(layout)
return nil
}
View on GitHub (pinned to 8b5af0694b)
Solutions
- Use Go duration syntax with units: `ns`, `us`, `ms`, `s`, `m`, `h` (compose, e.g. `24h` for a day)
- Replace `1day` with `24h`, `30 days` with `720h`
- To get the difference between two timestamps, subtract to get a duration contextually or compute via unix timestamps instead of passing a timestamp as the rhs duration
- Validate the duration string format before running the expression
Example fix
// before: yq 'now - 1day' -> unable to parse duration [1day] // after yq 'now - 24h'
Defensive patterns
Strategy: validation
Validate before calling
// validate a Go-parseable duration before passing it to yq
import (
"fmt"
"time"
"regexp"
)
var goDuration = regexp.MustCompile(`^-?[0-9]+(\.[0-9]+)?(ns|us|ms|s|m|h)$`)
func validateDuration(s string) error {
if !goDuration.MatchString(s) {
return fmt.Errorf("not a Go duration: %s (use ns/us/ms/s/m/h units)", s)
}
_, err := time.ParseDuration(s)
return err
} Type guard
func isGoDuration(s string) bool {
_, err := time.ParseDuration(s)
return err == nil
} Try / catch
// Go caller wrapping yq run
if err := runYq(expr); err != nil {
var durErr *fmt.WrapError
if strings.Contains(err.Error(), "unable to parse duration") {
return fmt.Errorf("fix duration to Go syntax (h/m/s), e.g. 24h: %w", err)
}
return err
} Prevention
- Only use Go duration units (ns/us/ms/s/m/h); convert days/weeks to hours manually (1d=24h)
- Never pass a timestamp as the duration operand of a datetime subtraction
- Always include units — bare numbers fail ParseDuration
When it happens
Trigger: `yq 'now - 1day'` (Go durations don't support 'day'), `.createdAt - "2 weeks"`, or subtracting a non-duration value like a number or timestamp from a datetime field: `.start - .end` where both are timestamps.
Common situations: Using human-friendly durations (`1d`, `2w`, `30 days`) that Go's ParseDuration rejects; forgetting units (`1h` works, `1` doesn't); accidentally subtracting a second timestamp instead of a duration when computing a difference of dates.
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.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- could not find %v for format_time
- %v: could not parse %v as an int: %w
- must provide a date time format string and an expression, e.
- no support for input format
- aborted
AI-assisted analysis of mikefarah/yq@8b5af0694b (2026-09-05).
Data as JSON: /api/errors/ea81df52abd31605.
Report an issue: GitHub.