{"record":{"id":"e8516c89e723023d","repo":"caddyserver/caddy","slug":"regexp-pattern-cannot-be-empty","errorCode":null,"errorMessage":"regexp pattern cannot be empty","messagePattern":"regexp pattern cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/logging/filters.go","lineNumber":1004,"sourceCode":"\n\t\t// Ensure result doesn't exceed max length after each operation\n\t\tif len(result) > maxInputLength {\n\t\t\tresult = result[:maxInputLength]\n\t\t}\n\t}\n\treturn result\n}\n\n// AddOperation adds a single regexp operation to the filter with validation.\n// This is used when merging multiple RegexpFilter instances.\nfunc (f *MultiRegexpFilter) AddOperation(rawRegexp, value string) error {\n\t// Security checks\n\tif len(f.Operations) >= maxRegexpOperations {\n\t\treturn fmt.Errorf(\"cannot add operation: maximum %d operations allowed\", maxRegexpOperations)\n\t}\n\n\tif rawRegexp == \"\" {\n\t\treturn fmt.Errorf(\"regexp pattern cannot be empty\")\n\t}\n\n\tif len(rawRegexp) > maxPatternLength {\n\t\treturn fmt.Errorf(\"regexp pattern too long: %d characters (maximum %d)\", len(rawRegexp), maxPatternLength)\n\t}\n\n\tf.Operations = append(f.Operations, regexpFilterOperation{\n\t\tRawRegexp: rawRegexp,\n\t\tValue:     value,\n\t})\n\treturn nil\n}\n\n// RenameFilter is a Caddy log field filter that\n// renames the field's key with the indicated name.\ntype RenameFilter struct {\n\tName string `json:\"name,omitempty\"`\n}","sourceCodeStart":986,"sourceCodeEnd":1022,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/logging/filters.go#L986-L1022","documentation":"AddOperation on MultiRegexpFilter rejects an empty rawRegexp argument. It is the programmatic counterpart of the Validate() empty-pattern check: an empty pattern is treated as invalid input rather than a match-everything wildcard.","triggerScenarios":"Calling mf.AddOperation(\"\", value) (or with a variable that resolved to empty, e.g. an unset config key) when merging RegexpFilter instances.","commonSituations":"Merge loops that pass filter structs with zero-value Search fields; config-driven code where the search expression failed to populate; empty string slipping through after placeholder substitution.","solutions":["Skip empty patterns in the merge loop before calling AddOperation","Fix the source of the empty value (missing key in JSON/Caddyfile)","Use \".*\" if a catch-all was intended"],"exampleFix":"// before\nmf.AddOperation(cfg.Search, cfg.Replace) // cfg.Search == \"\"\n\n// after\nif cfg.Search != \"\" {\n    if err := mf.AddOperation(cfg.Search, cfg.Replace); err != nil {\n        return err\n    }\n}","handlingStrategy":"validation","validationCode":"if rawRegexp == \"\" { return nil /* skip empty */ }\nif err := mf.AddOperation(rawRegexp, value); err != nil { return err }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Filter zero-value Search fields before merging RegexpFilters","Assert non-empty patterns in config unit tests"],"tags":["caddy","logging","regexp","validation"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}