{"record":{"id":"c6e9bc0caaea7b05","repo":"grpc/grpc-go","slug":"recovered-from-panic-during-resource-parsing-reso","errorCode":null,"errorMessage":"recovered from panic during resource parsing, resource: %v, panic: %v","messagePattern":"recovered from panic during resource parsing, resource: (.+?), panic: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/clients/xdsclient/channel.go","lineNumber":260,"sourceCode":"\ttimestamp := time.Now()\n\tmd := xdsresource.UpdateMetadata{\n\t\tVersion:   resp.version,\n\t\tTimestamp: timestamp,\n\t}\n\topts := &DecodeOptions{\n\t\tConfig:       xc.clientConfig,\n\t\tServerConfig: xc.serverConfig,\n\t}\n\n\ttopLevelErrors := make([]error, 0)          // Tracks deserialization errors, where we don't have a resource name.\n\tperResourceErrors := make(map[string]error) // Tracks resource validation errors, where we have a resource name.\n\tret := make(map[string]dataAndErrTuple)     // Return result, a map from resource name to either resource data or error.\n\tfor _, r := range resp.resources {\n\t\tresult, err := func() (res *DecodeResult, err error) {\n\t\t\tdefer func() {\n\t\t\t\tif envconfig.XDSRecoverPanicInResourceParsing {\n\t\t\t\t\tif p := recover(); p != nil {\n\t\t\t\t\t\terr = fmt.Errorf(\"recovered from panic during resource parsing, resource: %v, panic: %v\", r, p)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}()\n\t\t\treturn rType.Decoder.Decode(NewAnyProto(r), *opts)\n\t\t}()\n\n\t\t// Name field of the result is left unpopulated only when resource\n\t\t// deserialization fails.\n\t\tname := \"\"\n\t\tif result == nil && err == nil {\n\t\t\txc.logger.Errorf(\"Decode() returned nil result and nil error for resource: %v\", r)\n\t\t\tcontinue\n\t\t}\n\t\tif result != nil {\n\t\t\tname = xdsresource.ParseName(result.Name).String()\n\t\t}\n\t\tif err == nil {\n\t\t\tret[name] = dataAndErrTuple{Resource: result.Resource}","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/xds/clients/xdsclient/channel.go#L242-L278","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the panic stack in the log (the %v includes the recovered value) and identify which decoder/resource type faulted.","Report or fix the decoder bug; for custom ResourceType implementations, add nil/type checks before assertions.","If the resource itself is bad, correct the server-side configuration so the client stops receiving it.","Disable the env override only if you need the process to crash for debugging; leaving it on is recommended in production."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// The client converts the panic into a NACK; surface NACK errors via the\n// ResourceError watcher callback and log the resource for follow-up.\nfunc (w *myWatcher) ResourceError(err error, done func()) {\n    defer done()\n    logger.Errorf(\"xDS resource NACK: %v\", err)\n}","preventionTips":["Keep GRPC_XDS_RECOVER_PANIC_IN_RESOURCE_PARSING enabled in production to avoid process crashes.","For custom ResourceType decoders, add nil/type checks and unit tests with malformed inputs.","Track which resource triggered the panic from the log and disable/fix it server-side."],"tags":["grpc","xds","ads","panic","decoder"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}