{"record":{"id":"ea81df52abd31605","repo":"mikefarah/yq","slug":"unable-to-parse-duration-v-w-ea81df","errorCode":null,"errorMessage":"unable to parse duration [%v]: %w","messagePattern":"unable to parse duration \\[(.+?)\\]: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/yqlib/operator_subtract.go","lineNumber":143,"sourceCode":"\t\ttarget.Value = fmt.Sprintf(\"%v\", result)\n\t} else {\n\t\treturn fmt.Errorf(\"%v cannot be added to %v\", lhs.Tag, rhs.Tag)\n\t}\n\n\treturn nil\n}\n\nfunc subtractDateTime(layout string, target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {\n\tvar durationStr string\n\tif strings.HasPrefix(rhs.Value, \"-\") {\n\t\tdurationStr = rhs.Value[1:]\n\t} else {\n\t\tdurationStr = \"-\" + rhs.Value\n\t}\n\tduration, err := time.ParseDuration(durationStr)\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to parse duration [%v]: %w\", rhs.Value, err)\n\t}\n\n\tcurrentTime, err := parseDateTime(layout, lhs.Value)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tnewTime := currentTime.Add(duration)\n\ttarget.Value = newTime.Format(layout)\n\treturn nil\n}\n","sourceCodeStart":125,"sourceCodeEnd":155,"githubUrl":"https://github.com/mikefarah/yq/blob/8b5af0694bb82b41d4ae180fac9972029066f90a/pkg/yqlib/operator_subtract.go#L125-L155","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","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"],"exampleFix":"// before: yq 'now - 1day'  -> unable to parse duration [1day]\n// after\nyq 'now - 24h'","handlingStrategy":"validation","validationCode":"// validate a Go-parseable duration before passing it to yq\nimport (\n  \"fmt\"\n  \"time\"\n  \"regexp\"\n)\nvar goDuration = regexp.MustCompile(`^-?[0-9]+(\\.[0-9]+)?(ns|us|ms|s|m|h)$`)\nfunc validateDuration(s string) error {\n  if !goDuration.MatchString(s) {\n    return fmt.Errorf(\"not a Go duration: %s (use ns/us/ms/s/m/h units)\", s)\n  }\n  _, err := time.ParseDuration(s)\n  return err\n}","typeGuard":"func isGoDuration(s string) bool {\n    _, err := time.ParseDuration(s)\n    return err == nil\n}","tryCatchPattern":"// Go caller wrapping yq run\nif err := runYq(expr); err != nil {\n    var durErr *fmt.WrapError\n    if strings.Contains(err.Error(), \"unable to parse duration\") {\n        return fmt.Errorf(\"fix duration to Go syntax (h/m/s), e.g. 24h: %w\", err)\n    }\n    return err\n}","preventionTips":["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"],"tags":["yq","datetime","duration","parsing"],"backgroundTag":"invalid-duration-format","analyzedSha":"8b5af0694bb82b41d4ae180fac9972029066f90a","analyzedAt":"2026-09-05T10:57:22.766Z","contentChangedAt":"2026-09-05T10:57:22.766Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}