{"record":{"id":"1af7ae5a1090e169","repo":"argoproj/argo-workflows","slug":"invalid-maxage-w","errorCode":null,"errorMessage":"invalid maxAge: %w","messagePattern":"invalid maxAge: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/controller/operator.go","lineNumber":2378,"sourceCode":"\t\t\tmemoizationCache := woc.controller.cacheFactory.GetCache(controllercache.ConfigMapCache, processedTmpl.Memoize.Cache.ConfigMap.Name)\n\t\t\tif memoizationCache == nil {\n\t\t\t\tcacheErr := fmt.Errorf(\"cache could not be found or created\")\n\t\t\t\twoc.log.WithFields(logging.Fields{\"cacheName\": processedTmpl.Memoize.Cache.ConfigMap.Name}).WithError(cacheErr)\n\t\t\t\terrNode := woc.initializeNodeOrMarkError(ctx, node, nodeName, templateScope, orgTmpl, opts.boundaryID, opts.nodeFlag, cacheErr)\n\t\t\t\treturn errNode, cacheErr\n\t\t\t}\n\n\t\t\tentry, loadErr := memoizationCache.Load(ctx, processedTmpl.Memoize.Key)\n\t\t\tif loadErr != nil {\n\t\t\t\treturn woc.initializeNodeOrMarkError(ctx, node, nodeName, templateScope, orgTmpl, opts.boundaryID, opts.nodeFlag, loadErr), loadErr\n\t\t\t}\n\n\t\t\thit := entry.Hit()\n\t\t\tvar outputs *wfv1.Outputs\n\t\t\tif processedTmpl.Memoize.MaxAge != \"\" {\n\t\t\t\tmaxAge, parseErr := time.ParseDuration(processedTmpl.Memoize.MaxAge)\n\t\t\t\tif parseErr != nil {\n\t\t\t\t\tmaxAgeErr := fmt.Errorf(\"invalid maxAge: %w\", parseErr)\n\t\t\t\t\treturn woc.initializeNodeOrMarkError(ctx, node, nodeName, templateScope, orgTmpl, opts.boundaryID, opts.nodeFlag, maxAgeErr), maxAgeErr\n\t\t\t\t}\n\t\t\t\tmaxAgeOutputs, ok := entry.GetOutputsWithMaxAge(maxAge)\n\t\t\t\tif !ok {\n\t\t\t\t\t// The outputs are expired, so this cache entry is not hit\n\t\t\t\t\thit = false\n\t\t\t\t}\n\t\t\t\toutputs = maxAgeOutputs\n\t\t\t} else {\n\t\t\t\toutputs = entry.GetOutputs()\n\t\t\t}\n\n\t\t\tmemoizationStatus := &wfv1.MemoizationStatus{\n\t\t\t\tHit:       hit,\n\t\t\t\tKey:       processedTmpl.Memoize.Key,\n\t\t\t\tCacheName: processedTmpl.Memoize.Cache.ConfigMap.Name,\n\t\t\t}\n\t\t\tif hit {","sourceCodeStart":2360,"sourceCodeEnd":2396,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/controller/operator.go#L2360-L2396","documentation":"When a memoized template's cache entry is considered, executeTemplate parses memoize.maxAge as a Go duration. If the maxAge string in the template spec is not a valid duration (e.g. '1d', '24', 'day'), the controller returns 'invalid maxAge: %w' wrapping the time.ParseDuration error and marks the node as error via initializeNodeOrMarkError before the cache entry is ever consulted.","triggerScenarios":"A workflow template with spec.templates[].memoize.maxAge set to a string that time.ParseDuration cannot parse — e.g. missing unit ('30'), unsupported unit ('1d'), or typo ('12hh'). The error is returned by executeTemplate, which is reached via executeDAGTask, hooks, onExit, or normal operate().","commonSituations":"Users writing human-friendly durations like '1d' or '2w' (Go durations don't support days/weeks); values templated from config that end up empty or malformed; upgrading from a version that never validated maxAge.","solutions":["Fix memoize.maxAge in the template to a Go duration string with units, e.g. maxAge: \"24h\" instead of \"1d\".","Lint the workflow before submitting: argo lint <file> — note older linters may not validate maxAge, so validate durations manually.","If maxAge comes from a ConfigMap/parameter substitution, verify the resolved value with argo submit --dry-run --output json and inspect the memoize block.","Use only units supported by time.ParseDuration: ns, us (µs), ms, s, m, h (compose days as 24h)."],"exampleFix":"memoize:\n  key: my-cache\n# before\n  maxAge: \"1d\"\n# after\n  maxAge: \"24h\"","handlingStrategy":"validation","validationCode":"// Validate maxAge in your pipeline before applying the manifest\nimport \"time\"\nfunc validateMaxAge(s string) error {\n\t_, err := time.ParseDuration(s)\n\treturn err\n}\n// usage: validateMaxAge(memoize.MaxAge) must return nil before argo submit","typeGuard":"func isValidDuration(s string) bool {\n\t_, err := time.ParseDuration(s)\n\treturn s != \"\" && err == nil\n}","tryCatchPattern":null,"preventionTips":["Only use time.ParseDuration units: ns, us, ms, s, m, h — never 'd' or 'w'.","Add argo lint to CI for every workflow manifest.","If maxAge comes from templating, dry-run and inspect the resolved value first.","Add a unit test that parses every maxAge/timeout literal in your workflow library."],"tags":["argo-workflows","duration-parsing","memoization","config-error"],"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-08T05:18:18.240Z"}