{"record":{"id":"de6d916dd92ad99a","repo":"SigNoz/signoz","slug":"code-invalid-input-de6d91","errorCode":"CODE_INVALID_INPUT","errorMessage":"failed to parse duration text","messagePattern":"failed to parse duration text","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"pkg/valuer/text_duration.go","lineNumber":26,"sourceCode":"\t\"github.com/SigNoz/signoz/pkg/errors\"\n)\n\nvar _ Valuer = (*TextDuration)(nil)\n\n// TextDuration preserves the human-readable duration text as provided by the input.\n// It keeps the raw JSON bytes so serialization does not normalize values like\n// \"90m\" into \"1h30m0s\".\ntype TextDuration struct {\n\ttext  string\n\tvalue time.Duration\n}\n\n// ParseTextDuration parses a human-readable duration string.\n// This preserves the raw text so that it can be serialized back to JSON.\nfunc ParseTextDuration(s string) (TextDuration, error) {\n\td, err := time.ParseDuration(s)\n\tif err != nil {\n\t\treturn TextDuration{}, errors.Wrap(err, errors.TypeInvalidInput, errors.CodeInvalidInput, \"failed to parse duration text\")\n\t}\n\treturn TextDuration{text: s, value: d}, nil\n}\n\n// MustParseTextDuration parses a human-readable duration string, preserving\n// the raw text and panics if an error occurs.\nfunc MustParseTextDuration(s string) TextDuration {\n\td, err := ParseTextDuration(s)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn d\n}\n\n// Duration returns the [time.Duration] type.\nfunc (d TextDuration) Duration() time.Duration {\n\treturn d.value\n}","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/SigNoz/signoz/blob/5069bf80b08f1f00d7e014eccc09902f9871004f/pkg/valuer/text_duration.go#L8-L44","documentation":"ParseTextDuration converts a human-readable duration string into a TextDuration (which preserves the original text for round-tripping). It calls time.ParseDuration directly, so only Go-native syntax is accepted: ns, us/µs, ms, s, m, h with optional decimals; anything else fails with CODE_INVALID_INPUT.","triggerScenarios":"Calling ParseTextDuration (or JSON-unmarshaling a field typed TextDuration) with strings like \"1d\", \"30 minutes\", \"PT1H\", \"\" or \"1w\". Note GetEvalDelay and other callers forward user/API input here, so these surface from query params and JSON bodies.","commonSituations":"API clients assuming day/week units exist (\"7d\" is the classic Prometheus-style value that Go rejects); empty-string defaults from omitted config fields; ISO-8601 durations from other systems.","solutions":["Convert day/week values to hours: \"7d\" → \"168h\", \"1w\" → \"168h\"","Use compound Go syntax: \"1h30m\", \"0.5h\", \"90s\"","Default omitted fields to a valid literal like \"0s\" instead of empty string"],"exampleFix":"// before\ninterval := \"7d\"\nd, err := valuer.ParseTextDuration(interval)\n\n// after\ninterval := \"168h\"\nd, err := valuer.ParseTextDuration(interval)","handlingStrategy":"validation","validationCode":"if _, err := time.ParseDuration(s); err != nil {\n    s = convertHumanDuration(s) // e.g. \"7d\" -> \"168h\"\n}\ntd, err := valuer.ParseTextDuration(s)","typeGuard":"func isParsableDuration(s string) bool { _, err := time.ParseDuration(s); return err == nil }","tryCatchPattern":"td, err := valuer.ParseTextDuration(s)\nif err != nil {\n    td = valuer.MustParseTextDuration(\"1h\") // safe default\n}","preventionTips":["Never send 'd'/'w' units to Go duration fields","Convert day-based values to hours at the API boundary"],"tags":["duration","parse","textduration","validation"],"backgroundTag":"invalid-duration-format","analyzedSha":"5069bf80b08f1f00d7e014eccc09902f9871004f","analyzedAt":"2026-08-28T06:22:12.824Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}