grpc/grpc-go · error
header mutation disallowed by headerMutationRules for header
Error message
header mutation disallowed by headerMutationRules for header key %q
What it means
Returned by ApplyAdditions when a header the ext_proc server wants to add/modify is rejected by the configured HeaderMutationRules (AllowExpr/DisallowExpr) AND DisallowIsError is true. Without DisallowIsError the mutation is silently skipped (continue); with it, the data-plane RPC fails with gRPC status Unknown. The allow() function returns false if the key matches DisallowExpr or does not match a configured AllowExpr.
Source
Thrown at internal/xds/httpfilter/extconfig.go:158
}
value := header.GetValue()
if strings.HasSuffix(key, "-bin") {
value = string(header.GetRawValue())
}
if len(value) > maxHeaderSize {
return fmt.Errorf("invalid header mutation: value for header key %q exceeds the maximum length of %d bytes", key, maxHeaderSize)
}
// ValidatePair rejects values carrying bytes outside %x20-%x7E. It
// skips the value check for "-bin" keys, whose values the transport
// base64 encodes.
if err := imetadata.ValidatePair(key, value); err != nil {
return fmt.Errorf("invalid header mutation: %v", err)
}
if !hmr.allow(key) {
if hmr.DisallowIsError {
return fmt.Errorf("header mutation disallowed by headerMutationRules for header key %q", key)
}
continue
}
// Perform the mutation on output metadata using the append_action
// field from the header value option.
switch hvo.GetAppendAction() {
case v3corepb.HeaderValueOption_APPEND_IF_EXISTS_OR_ADD:
input.Append(key, value)
case v3corepb.HeaderValueOption_ADD_IF_ABSENT:
if input.Get(key) == nil {
input.Set(key, value)
}
case v3corepb.HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD:
input.Set(key, value)
case v3corepb.HeaderValueOption_OVERWRITE_IF_EXISTS:
if input.Get(key) != nil {
input.Set(key, value)View on GitHub (pinned to 0c51461d27)
Solutions
- Update the ext_proc server so it only mutates headers permitted by the configured allow/disallow regexes.
- If the mutation is intended, broaden allow_expression (or narrow disallow_expression) in the xDS HeaderMutationRules.
- If failing the RPC is too aggressive, set disallow_is_error=false to revert to silent skip behavior.
- Verify the regex with the same RE2 engine the client uses (Go regexp) to avoid dialect differences.
Example fix
// xDS EnvoyFilter/config - before
mutation_rules:
allow_expression: { regex: "^x-trace-.*$" }
disallow_is_error: true
// server sends "x-auth-token" -> RPC fails
// after: allow both, or downgrade to skip
mutation_rules:
allow_expression: { regex: "^x-(trace|auth)-.*$" }
disallow_is_error: true Defensive patterns
Strategy: validation
Validate before calling
// server-side: apply the same allow/disallow regexes before sending
func allowed(key string, allow, disallow *regexp.Regexp) bool {
if disallow != nil && disallow.MatchString(key) { return false }
if allow != nil { return allow.MatchString(key) }
return true
} Prevention
- Make the server aware of the configured allow/disallow regexes.
- Prefer disallow_is_error=false if silent skip fits your threat model.
- Test regexes with Go's RE2 (no backreferences).
- Tighten the server's emitted header set to match the policy.
When it happens
Trigger: xDS config sets mutation_rules with disallow_is_error=true and either an allow_expression that does not match the key, or a disallow_expression that does match it. The ext_proc server then attempts to mutate that key, hitting extconfig.go:158.
Common situations: A security policy disallows mutating x-auth-* but the ext_proc server tries to set it; an allow list was tightened and the server was not updated; the regex was written for Envoy semantics and behaves differently under Go's RE2.
Related errors
- header mutation disallowed by headerMutationRules for header
- invalid header mutation: value for header key %q exceeds the
- header key is empty
- header key %q is a pseudo-header
- header key %q is reserved
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/05323316d0ce81f0.
Report an issue: GitHub.