{"record":{"id":"41f17c7b45de9698","repo":"istio/istio","slug":"invalid-duration","errorCode":null,"errorMessage":"invalid duration","messagePattern":"invalid duration","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tools/bug-report/pkg/config/config.go","lineNumber":321,"sourceCode":"\nfunc (d *Duration) UnmarshalJSON(b []byte) error {\n\tvar v any\n\tif err := json.Unmarshal(b, &v); err != nil {\n\t\treturn err\n\t}\n\tswitch value := v.(type) {\n\tcase float64:\n\t\t*d = Duration(time.Duration(value))\n\t\treturn nil\n\tcase string:\n\t\ttmp, err := time.ParseDuration(value)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\t*d = Duration(tmp)\n\t\treturn nil\n\tdefault:\n\t\treturn errors.New(\"invalid duration\")\n\t}\n}\n","sourceCodeStart":303,"sourceCodeEnd":324,"githubUrl":"https://github.com/istio/istio/blob/8dc789c5cf17517c64e3c36cb3288230f149dfae/tools/bug-report/pkg/config/config.go#L303-L324","documentation":"bug-report's Duration type implements YAML/JSON unmarshaling: a float64 (JSON number) is cast to time.Duration nanoseconds, a string goes through time.ParseDuration, and any other type (bool, map, list, null-shaped non-null, or integer encoded oddly) yields 'invalid duration'. So the config key is present but has an unusable type.","triggerScenarios":"Writing `wait-timeout: true`, `timeout: [30]`, or `interval: 30` where the YAML scalar resolves to something other than number/string in the bug-report config (tools/bug-report). Numeric values are interpreted as nanoseconds, so `30` becomes 30ns — technically valid but almost certainly unintended.","commonSituations":"Hand-editing the bug-report YAML with a quoted complex value; templating tools injecting booleans or lists; users writing `5s` correctly but a stray character (e.g. `5s,`) breaking the string parse.","solutions":["Use a duration string with units: `wait-timeout: 5m` or `2m30s`.","If using a number, remember it means nanoseconds — prefer strings to avoid surprises.","Remove quotes/structural mistakes so the scalar stays a plain string."],"exampleFix":"# before\nwait-timeout: true\n\n# after\nwait-timeout: 5m","handlingStrategy":"type-guard","validationCode":"value := cfg[\"wait-timeout\"]\nswitch value.(type) {\ncase float64, string:\ndefault:\n    return fmt.Errorf(\"wait-timeout must be a number or duration string, got %T\", value)\n}","typeGuard":"func isDurationable(v any) bool {\n    switch v.(type) {\n    case float64, string:\n        return true\n    }\n    return false\n}","tryCatchPattern":"In custom unmarshalers, pre-check the node kind (scalar number or string) and return a typed error naming the config key; never accept bool/map/list for duration fields.","preventionTips":["Write durations as strings with units ('5m', '90s') in all configs.","Schema-validate bug-report configs before running the tool."],"tags":["istio","bug-report","yaml","configuration","duration"],"backgroundTag":null,"analyzedSha":"8dc789c5cf17517c64e3c36cb3288230f149dfae","analyzedAt":"2026-08-15T15:16:55.434Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}