{"record":{"id":"51f780f5dc2c55c4","repo":"argoproj/argo-workflows","slug":"invalid-ttl","errorCode":null,"errorMessage":"invalid TTL","messagePattern":"invalid TTL","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/ttl.go","lineNumber":58,"sourceCode":"\t\t}\n\t\tif before, ok := strings.CutSuffix(value, \"m\"); ok {\n\t\t\tminutes, err := strconv.Atoi(before)\n\t\t\t*l = TTL(time.Duration(minutes) * time.Minute)\n\t\t\treturn err\n\t\t}\n\t\tif before, ok := strings.CutSuffix(value, \"s\"); ok {\n\t\t\tseconds, err := strconv.Atoi(before)\n\t\t\t*l = TTL(time.Duration(seconds) * time.Second)\n\t\t\treturn err\n\t\t}\n\t\td, err := time.ParseDuration(value)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\t*l = TTL(d)\n\t\treturn nil\n\tdefault:\n\t\treturn errors.New(\"invalid TTL\")\n\t}\n}\n","sourceCodeStart":40,"sourceCodeEnd":61,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/config/ttl.go#L40-L61","documentation":"config.TTL's UnmarshalJSON only accepts JSON strings (with units d/h/m/s, empty string, or time.ParseDuration formats). Any non-string JSON value — a bare number, object, array, bool, or null — hits the default branch and returns \"invalid TTL\" while parsing the controller config (e.g. workflow TTLs / archiving settings).","triggerScenarios":"Setting a TTL field in the workflow-controller ConfigMap as a number (e.g. `ttlStrategy: {secondsSinceCompletion: ...}` is fine, but a TTL field like `ttl: 30` or `\"ttl\": {\"seconds\": 30}`) instead of a quoted duration string like \"30m\", \"24h\", or \"5d\".","commonSituations":"Users writing YAML that a YAML parser turns into an int (unquoted `ttl: 30`); copying configs between features where one expects a number (secondsSinceCompletion) and this one expects a string; upgrading and moving a TTL field into config where TTL unmarshalling applies.","solutions":["Quote the value and add a unit: `ttl: \"720h\"` or `ttl: \"30d\"`.","Accepted formats: \"\", \"5d\", \"12h\", \"30m\", \"45s\", or any Go time.ParseDuration string like \"1h30m\".","If you meant a numeric-seconds option, use the dedicated field (e.g. ttlStrategy.secondsAfterCompletion) instead of a TTL field.","Validate the controller ConfigMap by restarting the controller and checking logs for config parse errors."],"exampleFix":"# before\nworkflowDefaults: {}\narchive:\n  ttl: 30\n# after\narchive:\n  ttl: \"30d\"","handlingStrategy":"validation","validationCode":"// validate TTL config value before applying\nttl, ok := v.(string)\nif !ok {\n    return fmt.Errorf(\"TTL must be a string like \\\"30d\\\", \\\"12h\\\", \\\"30m\\\", got %T\", v)\n}\nif _, err := time.ParseDuration(strings.TrimSuffix(ttl, \"d\") + \"h\"); err != nil && !strings.HasSuffix(ttl, \"d\") {\n    return fmt.Errorf(\"invalid TTL duration %q\", ttl)\n}","typeGuard":"func isStringTTL(v any) (string, bool) {\n    s, ok := v.(string)\n    return s, ok\n}","tryCatchPattern":null,"preventionTips":["Always quote TTL values in YAML/JSON config: \"30d\", \"12h\"","Never use bare numbers for TTL fields","Remember supported units: d, h, m, s, or Go duration strings","Validate the controller ConfigMap after edits before rollout"],"tags":["config","json","unmarshal","argo"],"backgroundTag":"invalid-duration-format","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}