grpc/grpc-go · error

httpfilter: %v

Error message

httpfilter: %v

What it means

Raised by HeaderMutationRulesFromProto (extconfig.go:78) when the allow_expression regex in a HeaderMutationRules proto cannot be compiled. The library wraps the inner matcher.CompileSafeRegex error with the 'httpfilter:' prefix; an invalid regex means the rules cannot be enforced, so the filter config (ext_authz or ext_proc) is rejected.

Source

Thrown at internal/xds/httpfilter/extconfig.go:78

		if err != nil {
			return nil, err
		}
		matchers = append(matchers, sm)
	}
	return matchers, nil
}

// HeaderMutationRulesFromProto converts a protobuf HeaderMutationRules proto
// message to a HeaderMutationRules struct.
func HeaderMutationRulesFromProto(mr *v3mutationpb.HeaderMutationRules) (HeaderMutationRules, error) {
	var rules HeaderMutationRules
	if mr == nil {
		return rules, nil
	}
	if allowExpr := mr.GetAllowExpression(); allowExpr != nil {
		re, err := matcher.CompileSafeRegex(allowExpr.GetRegex())
		if err != nil {
			return rules, fmt.Errorf("httpfilter: %v", err)
		}
		rules.AllowExpr = re
	}
	if disallowExpr := mr.GetDisallowExpression(); disallowExpr != nil {
		re, err := matcher.CompileSafeRegex(disallowExpr.GetRegex())
		if err != nil {
			return rules, fmt.Errorf("httpfilter: %v", err)
		}
		rules.DisallowExpr = re
	}
	rules.DisallowAll = mr.GetDisallowAll().GetValue()
	rules.DisallowIsError = mr.GetDisallowIsError().GetValue()
	return rules, nil
}

// ApplyAdditions takes a set of header mutations (for additions and
// modifications) received from an external server and applies them to the
// provided metadata, subject to the rules defined in hmr.

View on GitHub (pinned to 03255a9237)

Solutions

  1. Read the inner %v — it is the exact RE2 syntax error with position.
  2. Replace the pattern with a valid RE2 regex (no backreferences, no lookahead); test it with `regexp.Compile` / `protoc` before publishing.
  3. Note CompileSafeRegex anchors the pattern as ^(?:PATTERN)$, so ensure your pattern is meant to match the whole header name.

Example fix

// before
//   allow_expression: { regex: "x-[a-z" }   // unclosed class -> error 366
//
// after
//   allow_expression: { regex: "x-[a-z]+" }
Defensive patterns

Strategy: validation

Validate before calling

// Pre-compile allow_expression the way the filter will (string_matcher.go:224-228,
// wrapped at extconfig.go:78).
func validateAllowRegex(re *envoy_type_matcher.RegexMatcher) error {
    if re == nil {
        return nil
    }
    if _, err := regexp.Compile(re.GetRegex()); err != nil {
        return fmt.Errorf("httpfilter: %w", err)
    }
    // CompileSafeRegex also anchors as ^(?:...)$; verify that compiles too.
    if _, err := regexp.Compile(fmt.Sprintf("^(?:%s)$", re.GetRegex())); err != nil {
        return err
    }
    return nil
}

Prevention

When it happens

Trigger: The decoder_header_mutation_rules / mutation_rules allow_expression.regex (RE2 syntax) is malformed, so regexp.Compile at string_matcher.go:225 fails and the error is propagated at extconfig.go:78.

Common situations: A regex with constructs RE2 rejects (e.g. backreferences '\1', unbalanced parentheses, invalid escape sequences); a typo like '[a-z' (unclosed class); copy-pasting a PCRE pattern into the xDS config.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/3b73fb72b6de1871. Report an issue: GitHub.