caddyserver/caddy · error
url_pattern expects a string argument
Error message
url_pattern expects a string argument
What it means
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.
Source
Thrown at modules/caddyhttp/urlpatternmatcher.go:138
}
}
// CELLibrary produces options that expose this matcher for use in CEL
// expression matchers.
//
// Example:
//
// expression url_pattern('/books/:id')
// expression url_pattern('/books/:id', 'https://example.com')
func (MatchURLPattern) CELLibrary(ctx caddy.Context) (cel.Library, error) {
pattern, err := CELMatcherImpl(
"url_pattern",
"url_pattern_request_string",
[]*cel.Type{cel.StringType},
func(data ref.Val) (RequestMatcherWithError, error) {
pattern, ok := data.Value().(string)
if !ok {
return nil, fmt.Errorf("url_pattern expects a string argument")
}
matcher := MatchURLPattern{Pattern: pattern}
err := matcher.Provision(ctx)
return &matcher, err
},
)
if err != nil {
return nil, err
}
patternWithBase, err := CELMatcherImpl(
"url_pattern",
"url_pattern_request_string_string",
[]*cel.Type{cel.StringType, cel.StringType},
func(data ref.Val) (RequestMatcherWithError, error) {
params, err := data.ConvertToNative(stringSliceType)View on GitHub (pinned to 50e54ee279)
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
Example fix
# before
expression url_pattern(req.uri.path + '/*')
# after
expression url_pattern('/*')
# or a plain matcher
path /* Defensive patterns
Strategy: type-guard
Validate before calling
// When building CEL matchers programmatically, assert the arg type before the call:
if len(args) == 1 {
if s, ok := args[0].(ref.Val).Value().(string); ok {
m := caddyhttp.MatchURLPattern{Pattern: s}
if err := m.Provision(ctx); err == nil {
matchers = append(matchers, &m)
}
}
} Type guard
func isStringVal(v ref.Val) bool {
_, ok := v.Value().(string)
return ok
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- unable to parse URL pattern: %w
- not implemented
- invalid action type
- %w, at %s:%d import chain ['%s']
- %w, at %s:%d
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/7336c900cf995934.
Report an issue: GitHub.