{"record":{"id":"7336c900cf995934","repo":"caddyserver/caddy","slug":"url-pattern-expects-a-string-argument","errorCode":null,"errorMessage":"url_pattern expects a string argument","messagePattern":"url_pattern expects a string argument","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/urlpatternmatcher.go","lineNumber":138,"sourceCode":"\t}\n}\n\n// CELLibrary produces options that expose this matcher for use in CEL\n// expression matchers.\n//\n// Example:\n//\n//\texpression url_pattern('/books/:id')\n//\texpression url_pattern('/books/:id', 'https://example.com')\nfunc (MatchURLPattern) CELLibrary(ctx caddy.Context) (cel.Library, error) {\n\tpattern, err := CELMatcherImpl(\n\t\t\"url_pattern\",\n\t\t\"url_pattern_request_string\",\n\t\t[]*cel.Type{cel.StringType},\n\t\tfunc(data ref.Val) (RequestMatcherWithError, error) {\n\t\t\tpattern, ok := data.Value().(string)\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"url_pattern expects a string argument\")\n\t\t\t}\n\n\t\t\tmatcher := MatchURLPattern{Pattern: pattern}\n\t\t\terr := matcher.Provision(ctx)\n\n\t\t\treturn &matcher, err\n\t\t},\n\t)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tpatternWithBase, err := CELMatcherImpl(\n\t\t\"url_pattern\",\n\t\t\"url_pattern_request_string_string\",\n\t\t[]*cel.Type{cel.StringType, cel.StringType},\n\t\tfunc(data ref.Val) (RequestMatcherWithError, error) {\n\t\t\tparams, err := data.ConvertToNative(stringSliceType)","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/urlpatternmatcher.go#L120-L156","documentation":"Returned from the CEL matcher factory for `url_pattern` when the argument value passed to the matcher function is not a Go string. CEL's type system already constrains the declared argument list to []&cel.Type{cel.StringType}, so in practice this error is only reachable when the matcher is constructed programmatically with a non-string ref.Val. For Caddyfile/JSON users the fix is to pass the pattern as a quoted string literal.","triggerScenarios":"Writing an expression matcher like `expression url_pattern(/books/:id)` where a CEL variable or computed value of non-string type flows into the call, or embedding a request-derived value instead of a literal. The CELLibrary closure calls data.Value().(string); when the type assertion fails this error replaces the pattern.","commonSituations":"Using an unquoted pattern token that CEL parses as something else; trying to build the pattern dynamically from header values (`url_pattern(req.header.X)`); copy-pasting a wildcard matcher (`path *`) style argument into url_pattern.","solutions":["Pass a quoted string literal: `expression url_pattern('/books/:id')`","Do not feed request-dependent CEL values into url_pattern — patterns are compiled once at config load, not per request","If composing patterns dynamically is needed, use the `path` or `query` matchers instead","Check the CEL expression compiles with `caddy adapt --validate` before deploying"],"exampleFix":"# before\nexpression url_pattern(req.uri.path + '/*')\n\n# after\nexpression url_pattern('/*')\n# or a plain matcher\npath /*","handlingStrategy":"type-guard","validationCode":"// When building CEL matchers programmatically, assert the arg type before the call:\nif len(args) == 1 {\n    if s, ok := args[0].(ref.Val).Value().(string); ok {\n        m := caddyhttp.MatchURLPattern{Pattern: s}\n        if err := m.Provision(ctx); err == nil {\n            matchers = append(matchers, &m)\n        }\n    }\n}","typeGuard":"func isStringVal(v ref.Val) bool {\n    _, ok := v.Value().(string)\n    return ok\n}","tryCatchPattern":null,"preventionTips":["Always quote url_pattern arguments in Caddyfile expressions","Prefer plain path/query matchers when the pattern is static","Validate expressions with `caddy adapt --validate` before deploying"],"tags":["cel","expression","urlpattern","caddyfile","caddyhttp"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}