caddyserver/caddy · warning
missing 'req' argument
Error message
missing 'req' argument
What it means
While rotating an ECH key, Caddy marks the old config's metadata as Replaced and json.Marshal of that metadata (echConfigMeta, which includes publication history maps with time.Time values) failed. Marshal failures here are practically impossible with well-formed structs — this indicates memory corruption or an unsupported dynamic value, and mainly serves as a defensive error path.
Source
Thrown at modules/caddyhttp/celmatcher.go:481
}
// CELMatcherDecorator matches a call overload generated by a CEL macro
// that takes a single argument, and optimizes the implementation to precompile
// the matcher and return a function that references the precompiled and
// provisioned matcher.
func CELMatcherDecorator(funcName string, fac any) interpreter.InterpretableDecorator {
return func(i interpreter.Interpretable) (interpreter.Interpretable, error) {
call, ok := i.(interpreter.InterpretableCall)
if !ok {
return i, nil
}
if call.OverloadID() != funcName {
return i, nil
}
callArgs := call.Args()
reqAttr, ok := callArgs[0].(interpreter.InterpretableAttribute)
if !ok {
return nil, errors.New("missing 'req' argument")
}
nsAttr, ok := reqAttr.Attr().(interpreter.NamespacedAttribute)
if !ok {
return nil, errors.New("missing 'req' argument")
}
varNames := nsAttr.CandidateVariableNames()
if len(varNames) != 1 || len(varNames) == 1 && varNames[0] != CELRequestVarName {
return nil, errors.New("missing 'req' argument")
}
matcherData, ok := callArgs[1].(interpreter.InterpretableConst)
if !ok {
// If the matcher arguments are not constant, then this means
// they contain a Caddy placeholder reference and the evaluation
// and matcher provisioning should be handled at dynamically.
return i, nil
}
if factory, ok := fac.(CELMatcherWithErrorFactory); ok {View on GitHub (pinned to 50e54ee279)
Solutions
- Treat as a bug: collect the wrapped error and report it upstream with the Caddy version.
- Restart the instance; rotation will re-attempt and re-derive metadata.
- If persistent, reset the ech/configs storage folder to regenerate clean metadata.
Defensive patterns
Strategy: try-catch
Try / catch
if err := rotateECHKeys(...); err != nil { if strings.Contains(err.Error(), "marshaling updated ECH config metadata") { /* defensive path: log details, restart to rebuild state */ } } Prevention
- Treat occurrence as a bug: record version + error and report upstream.
- Restart to rebuild metadata from persisted state.
- Keep Caddy updated; defensive marshal paths are revised with fixes.
When it happens
Trigger: json.Marshal(ech.configs[publicName][i].meta) returns an error, e.g. an unmarshalable type injected into the meta struct, or a NaN/unsupported value in publication history timestamps.
Common situations: Almost never seen in practice; would surface only from a bug in Caddy or a plugin writing invalid values into echConfigMeta. If seen, suspect a corrupted build or memory issue.
Related errors
- --output is required
- cannot reuse socket %v: unix socket is already in use by ano
- unsupported type
- private key does not match issuer public key
- syntax error: unexpected token '%s', expecting '%s', at %s:%
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/7638aacd2a5b7fb2.
Report an issue: GitHub.