{"record":{"id":"54625cf05bbad9b6","repo":"gohugoio/hugo","slug":"cannot-convert-v-to-time-duration","errorCode":null,"errorMessage":"cannot convert %v to time.Duration","messagePattern":"cannot convert (.+?) to time\\.Duration","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/types/convert.go","lineNumber":40,"sourceCode":"\n\t\"github.com/spf13/cast\"\n)\n\n// ToDuration converts v to time.Duration.\n// See ToDurationE if you need to handle errors.\nfunc ToDuration(v any) time.Duration {\n\td, _ := ToDurationE(v)\n\treturn d\n}\n\n// ToDurationE converts v to time.Duration.\nfunc ToDurationE(v any) (time.Duration, error) {\n\tif n := cast.ToInt(v); n > 0 {\n\t\treturn time.Duration(n) * time.Millisecond, nil\n\t}\n\td, err := time.ParseDuration(cast.ToString(v))\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"cannot convert %v to time.Duration\", v)\n\t}\n\treturn d, nil\n}\n\n// ToStringSlicePreserveString is the same as ToStringSlicePreserveStringE,\n// but it never fails.\nfunc ToStringSlicePreserveString(v any) []string {\n\tvv, _ := ToStringSlicePreserveStringE(v)\n\treturn vv\n}\n\n// ToStringSlicePreserveStringE converts v to a string slice.\n// If v is a string, it will be wrapped in a string slice.\nfunc ToStringSlicePreserveStringE(v any) ([]string, error) {\n\tif v == nil {\n\t\treturn nil, nil\n\t}\n\tif sds, ok := v.(string); ok {","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/common/types/convert.go#L22-L58","documentation":"Returned by types.ToDurationE when neither the integer-fast-path (cast.ToInt > 0) nor time.ParseDuration succeeds. ToDuration treats positive integers as milliseconds; everything else must be a Go duration string like '30s', '5m', '2h45m'.","triggerScenarios":"Calling types.ToDurationE with a malformed duration string (e.g. 'fast', '5 min', '1d'), an empty string with no positive integer, or a non-string non-int type that cast cannot coerce.","commonSituations":"Config values for `timeout`, `caches` expiry, or build timeouts expressed in non-Go syntax (e.g. '1 day', '500ms' is fine, but '500' without a unit fallback works because the int path treats it as ms).","solutions":["Use Go duration syntax: '30s', '5m', '2h'.","For millisecond counts, pass a plain integer (e.g. 500 → 500ms).","Validate the field against time.ParseDuration in a config lint step."],"exampleFix":"// before\ntimeout: \"5 minutes\"\n// after\ntimeout: \"5m\"","handlingStrategy":"validation","validationCode":"func parseDur(s any) (time.Duration, error) {\n  if n := cast.ToInt(s); n > 0 { return time.Duration(n) * time.Millisecond, nil }\n  return time.ParseDuration(cast.ToString(s))\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use Go duration syntax in all time-related config keys.","Add a config validator that runs time.ParseDuration on duration fields.","Document that bare integers are interpreted as milliseconds."],"tags":["types","duration","time","config","convert"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}