caddyserver/caddy · error
invalid action type
Error message
invalid action type
What it means
filterAction.IsValid() in the logging module rejects any query-filter action type that is not one of the three literals 'replace', 'hash', or 'delete'. It is returned by QueryFilter.Validate() during config provisioning, so it fails at load time, never at request time. The value comes straight from the 'type' field of an action object in the query filter config.
Source
Thrown at modules/logging/filters.go:306
const (
// Replace value(s).
replaceAction filterAction = "replace"
// Hash value(s).
hashAction filterAction = "hash"
// Delete.
deleteAction filterAction = "delete"
)
func (a filterAction) IsValid() error {
switch a {
case replaceAction, deleteAction, hashAction:
return nil
}
return errors.New("invalid action type")
}
type queryFilterAction struct {
// `replace` to replace the value(s) associated with the parameter(s), `hash` to replace them with the 4 initial bytes of the SHA-256 of their content or `delete` to remove them entirely.
Type filterAction `json:"type"`
// The name of the query parameter.
Parameter string `json:"parameter"`
// The value to use as replacement if the action is `replace`.
Value string `json:"value,omitempty"`
}
// QueryFilter is a Caddy log field filter that filters
// query parameters from a URL.
//
// This filter updates the logged URL string to remove, replace or hash
// query parameters containing sensitive data. For instance, it can beView on GitHub (pinned to 50e54ee279)
Solutions
- Change the action type to exactly one of: replace, hash, or delete (lowercase)
- If using the Caddyfile, use the documented forms: replace <param> <value>, hash <param>, delete <param>
- Validate the logging config with caddy validate --config <file> --adapter <adapter> before deploying
- If 'replace' is chosen, also include the required 'value' field
Example fix
// before
{
"logs": {
"log0": {
"encoder": {
"format": "filter",
"wrap": {"format": "json"},
"fields": {
"uri": {
"filter": "query",
"actions": [{"type": "redact", "parameter": "token"}]
}
}
}
}
}
}
// after
"actions": [{"type": "delete", "parameter": "token"}] Defensive patterns
Strategy: validation
Validate before calling
var validActions = map[string]bool{"replace": true, "hash": true, "delete": true}
func validateQueryFilter(cfg map[string]any) error {
for _, f := range cfg["actions"].([]any) {
a := f.(map[string]any)
if !validActions[a["type"].(string)] {
return fmt.Errorf("invalid action type %q: use replace, hash, or delete", a["type"])
}
}
return nil
} Type guard
type FilterAction string
func (a FilterAction) Valid() bool {
switch a {
case "replace", "hash", "delete":
return true
}
return false
} Prevention
- Use the Caddyfile query filter syntax (replace/hash/delete) instead of raw JSON where possible
- Lint logging config in CI with caddy validate
- Remember action names are lowercase and case-sensitive
When it happens
Trigger: JSON config with log encoder filter {"filter": "query", "actions": [{"type": "redact", "parameter": "token"}]}; typo like "delelte" or "Hash" (case-sensitive); passing an action object without a recognized type value.
Common situations: Hand-writing the logs JSON config instead of using the Caddyfile syntax; porting a redaction config from another tool whose action names differ (e.g. 'remove', 'mask'); uppercase or localized variants of the action names.
Related errors
- include and exclude must not intersect, but found %s in both
- unrecognized log level: %s
- %s is %w
- no identifiers configured
- adapting config using %s: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/de0fe81d4aeca67a.
Report an issue: GitHub.