{"record":{"id":"fa64b63f4a8607a2","repo":"crowdsecurity/crowdsec","slug":"while-parsing-stash-ttl-w","errorCode":null,"errorMessage":"while parsing stash ttl: %w","messagePattern":"while parsing stash ttl: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/parser/stash.go","lineNumber":81,"sourceCode":"\tvar err error\n\n\trs := &RuntimeStash{Config: s}\n\n\trs.ValueExpression, err = expr.Compile(s.Value,\n\t\texprhelpers.GetExprOptions(map[string]any{\"evt\": &pipeline.Event{}})...)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"while compiling stash value expression: %w\", err)\n\t}\n\n\trs.KeyExpression, err = expr.Compile(s.Key,\n\t\texprhelpers.GetExprOptions(map[string]any{\"evt\": &pipeline.Event{}})...)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"while compiling stash key expression: %w\", err)\n\t}\n\n\trs.TTLVal, err = time.ParseDuration(s.TTL)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"while parsing stash ttl: %w\", err)\n\t}\n\n\t// init the cache, does it make sense to create it here just to be sure everything is fine ?\n\n\tcacheCfg := cache.CacheCfg{\n\t\tSize:     s.MaxMapSize,\n\t\tTTL:      rs.TTLVal,\n\t\tName:     s.Name,\n\t\tStrategy: s.Strategy,\n\t\tLogLevel: logger.Logger.GetLevel(),\n\t}\n\n\tif err = cache.CacheInit(cacheCfg, cacheCfg.NewLogger()); err != nil {\n\t\treturn nil, fmt.Errorf(\"while initializing cache: %w\", err)\n\t}\n\n\treturn rs, nil\n}","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/parser/stash.go#L63-L99","documentation":"RuntimeStash.Compile parses the stash configuration's 'ttl' with time.ParseDuration; an invalid duration string in the parser's stash configuration (e.g. '10' without a unit) makes compilation fail at parser load time.","triggerScenarios":"A stash `ttl:` value like \"1 hour\", \"3600\", \"1d\", or an empty-but-non-validated string is passed to time.ParseDuration during Compile.","commonSituations":"Users writing human-friendly durations (\"1 day\", \"one hour\"), plain numbers without units, or day units (\"1d\") which Go durations don't support.","solutions":["Use Go duration syntax for the stash ttl: \"1h\", \"30m\" — days are not supported, express them in hours","Omit the ttl directive if the stash should not expire"],"exampleFix":"// before\nttl: 1d\n// after\nttl: 24h","handlingStrategy":"validation","validationCode":"if _, err := time.ParseDuration(s.TTL); err != nil {\n    return fmt.Errorf(\"stash %q ttl %q is not a Go duration: %w\", s.Name, s.TTL, err)\n}","typeGuard":null,"tryCatchPattern":"if _, err := time.ParseDuration(ttlStr); err != nil {\n    return fmt.Errorf(\"bad ttl %q: use units s/m/h (no 'd')\", ttlStr)\n}","preventionTips":["Use only Go duration units: ns, us, ms, s, m, h — never 'd'.","Always give a unit (3600 alone is invalid; write 1h)."],"tags":["parser","stash","duration","config"],"backgroundTag":"invalid-duration-format","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}