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

  1. Pass a quoted string literal: `expression url_pattern('/books/:id')`
  2. Do not feed request-dependent CEL values into url_pattern — patterns are compiled once at config load, not per request
  3. If composing patterns dynamically is needed, use the `path` or `query` matchers instead
  4. 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

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


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/7336c900cf995934. Report an issue: GitHub.