grpc/grpc-go · error
extproc: input metadata is nil
Error message
extproc: input metadata is nil
What it means
Raised by (*HeaderMutationRules).ApplyAdditions (extconfig.go:120) when the input metadata argument is nil. The method's contract (documented at extconfig.go:114 'The input metadata must not be nil') requires a non-nil metadata.MD to mutate; a nil input is a programmer error in the caller. In the shipped filter, ApplyAdditions is called from extproc applyMutations (ext_proc.go:1377) with the stream's metadata, which is expected to be non-nil.
Source
Thrown at internal/xds/httpfilter/extconfig.go:120
// key and value, and checks if the mutation is permitted by the AllowExpr and
// DisallowExpr regular expressions.
//
// The following headers are always ignored:
// - Pseudo-headers (keys starting with ':').
// - The 'host' header.
// - Headers with non-lowercase keys.
// - Headers with keys or values exceeding 16384 bytes.
//
// If a mutation is disallowed and DisallowIsError is true, an error is
// returned. Otherwise, the disallowed mutation is silently ignored.
//
// The input metadata must not be nil.
func (hmr *HeaderMutationRules) ApplyAdditions(hvos []*v3corepb.HeaderValueOption, input metadata.MD) error {
if hmr == nil {
hmr = &HeaderMutationRules{}
}
if input == nil {
return fmt.Errorf("extproc: input metadata is nil")
}
if hmr.DisallowAll {
return nil
}
for _, hvo := range hvos {
header := hvo.GetHeader()
key := header.GetKey()
if len(key) == 0 || key[0] == ':' || key == "host" || key != strings.ToLower(key) || len(key) > 16384 {
continue
}
value := header.GetValue()
if strings.HasSuffix(key, "-bin") {
value = string(header.GetRawValue())
}
if len(value) > 16384 {
continueView on GitHub (pinned to 03255a9237)
Solutions
- Ensure the metadata.MD passed to ApplyAdditions is always initialized — use metadata.MD{} (or the actual received headers) rather than a nil map.
- If you call applyMutations/ApplyAdditions directly, allocate md := metadata.MD{} before the call when no real headers exist.
- For extproc, confirm the stream path that reached applyMutations actually obtained outgoing/incoming metadata; a nil there indicates an upstream initialization bug to file against gRPC.
Example fix
// before
var md metadata.MD // nil map
err := hmr.ApplyAdditions(setHeaders, md)
// after
md := metadata.MD{} // non-empty, mutable map
err := hmr.ApplyAdditions(setHeaders, md) Defensive patterns
Strategy: validation
Validate before calling
// Guard the ApplyAdditions contract (extconfig.go:119-121).
func safeApplyAdditions(hmr *httpfilter.HeaderMutationRules, hvos []*v3corepb.HeaderValueOption, md metadata.MD) error {
if md == nil {
md = metadata.MD{} // never pass nil; method requires non-nil input
}
return hmr.ApplyAdditions(hvos, md)
} Prevention
- Always initialize metadata (even as metadata.MD{}) before passing to ApplyAdditions/applyMutations.
- Treat 'input metadata must not be nil' as a hard precondition — add a nil check in calling code.
- If you call applyMutations in a custom integration, ensure the metadata was actually received first.
When it happens
Trigger: ApplyAdditions is invoked with input == nil. In production this means the filter implementation passed a nil metadata.MD into applyMutations; in tests/tools it means a direct caller forgot to allocate metadata before calling.
Common situations: A direct unit test of HeaderMutationRules passes nil for the metadata; a custom filter integration that constructs a HeaderMutationRules and calls ApplyAdditions on a response path where no metadata was received yet; a regression in the extproc stream handling that fails to lazily initialize metadata.
Related errors
- extproc: header mutation disallowed by headerMutationRules f
- extproc: header mutation disallowed by headerMutationRules f
- httpfilter: %v
- extproc: invalid request body mode %v: want %q or %q
- extproc: invalid response body mode %v: want %q or %q
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/e3240a718f8c12cd.
Report an issue: GitHub.