grpc/grpc-go · error

recovered from panic during resource parsing, resource: %v,

Error message

recovered from panic during resource parsing, resource: %v, panic: %v

What it means

Emitted (as a returned error, leading to a NACK) when a ResourceType.Decoder.Decode call panics and envconfig.XDSRecoverPanicInResourceParsing is enabled. The panic is recovered into this error message so one malformed resource does not crash the process; the resource is treated as a per-resource/top-level decode error and NACKed to the server.

Source

Thrown at internal/xds/clients/xdsclient/channel.go:260

	timestamp := time.Now()
	md := xdsresource.UpdateMetadata{
		Version:   resp.version,
		Timestamp: timestamp,
	}
	opts := &DecodeOptions{
		Config:       xc.clientConfig,
		ServerConfig: xc.serverConfig,
	}

	topLevelErrors := make([]error, 0)          // Tracks deserialization errors, where we don't have a resource name.
	perResourceErrors := make(map[string]error) // Tracks resource validation errors, where we have a resource name.
	ret := make(map[string]dataAndErrTuple)     // Return result, a map from resource name to either resource data or error.
	for _, r := range resp.resources {
		result, err := func() (res *DecodeResult, err error) {
			defer func() {
				if envconfig.XDSRecoverPanicInResourceParsing {
					if p := recover(); p != nil {
						err = fmt.Errorf("recovered from panic during resource parsing, resource: %v, panic: %v", r, p)
					}
				}
			}()
			return rType.Decoder.Decode(NewAnyProto(r), *opts)
		}()

		// Name field of the result is left unpopulated only when resource
		// deserialization fails.
		name := ""
		if result == nil && err == nil {
			xc.logger.Errorf("Decode() returned nil result and nil error for resource: %v", r)
			continue
		}
		if result != nil {
			name = xdsresource.ParseName(result.Name).String()
		}
		if err == nil {
			ret[name] = dataAndErrTuple{Resource: result.Resource}

View on GitHub (pinned to 03255a9237)

Solutions

  1. Read the panic stack in the log (the %v includes the recovered value) and identify which decoder/resource type faulted.
  2. Report or fix the decoder bug; for custom ResourceType implementations, add nil/type checks before assertions.
  3. If the resource itself is bad, correct the server-side configuration so the client stops receiving it.
  4. Disable the env override only if you need the process to crash for debugging; leaving it on is recommended in production.
Defensive patterns

Strategy: fallback

Try / catch

// The client converts the panic into a NACK; surface NACK errors via the
// ResourceError watcher callback and log the resource for follow-up.
func (w *myWatcher) ResourceError(err error, done func()) {
    defer done()
    logger.Errorf("xDS resource NACK: %v", err)
}

Prevention

When it happens

Trigger: A specific resource in an ADS response triggers a panic inside a registered ResourceType decoder (nil dereference, index out of range, assertion failure). Only seen when GRPC_XDS_RECOVER_PANIC_IN_RESOURCE_PARSING-style env override is on; otherwise the panic propagates.

Common situations: A malformed or unexpected resource shape from the server exposing a decoder bug, a custom ResourceType implementation with a nil pointer path, or a proto version mismatch causing a type assertion to fail inside the decoder.

Related errors


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