{"record":{"id":"83e6c7491becdb2c","repo":"hyperledger/fabric","slug":"config-envelope-has-nil-config","errorCode":null,"errorMessage":"config envelope has nil config","messagePattern":"config envelope has nil config","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/configtx/validator.go","lineNumber":168,"sourceCode":"\t}\n\n\treturn &cb.ConfigEnvelope{\n\t\tConfig: &cb.Config{\n\t\t\tSequence:     vi.sequence + 1,\n\t\t\tChannelGroup: channelGroup,\n\t\t},\n\t\tLastUpdate: configtx,\n\t}, nil\n}\n\n// Validate simulates applying a ConfigEnvelope to become the new config\nfunc (vi *ValidatorImpl) Validate(configEnv *cb.ConfigEnvelope) error {\n\tif configEnv == nil {\n\t\treturn errors.Errorf(\"config envelope is nil\")\n\t}\n\n\tif configEnv.Config == nil {\n\t\treturn errors.Errorf(\"config envelope has nil config\")\n\t}\n\n\tif configEnv.Config.Sequence != vi.sequence+1 {\n\t\treturn errors.Errorf(\"config currently at sequence %d, cannot validate config at sequence %d\", vi.sequence, configEnv.Config.Sequence)\n\t}\n\n\tconfigUpdateEnv, err := protoutil.EnvelopeToConfigUpdate(configEnv.LastUpdate)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tconfigMap, err := vi.authorizeUpdate(configUpdateEnv)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tchannelGroup, err := configMapToConfig(configMap, vi.namespace)\n\tif err != nil {","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/configtx/validator.go#L150-L186","documentation":"Validate returns this when the ConfigEnvelope is non-nil but its inner Config field is nil. The envelope shell exists but carries no actual configuration to apply, so validation cannot proceed. Like the nil-envelope check, it is a fast-fail guard before sequence and content checks.","triggerScenarios":"Calling Validate with a ConfigEnvelope whose Config is nil — e.g., an envelope constructed as &cb.ConfigEnvelope{} without setting Config, or one deserialized from an empty/partial payload.","commonSituations":"Hand-constructed ConfigEnvelope objects in tests or tools; proto unmarshaling from truncated payloads yielding an empty message; code paths that set only ChannelGroup or Sequence on the wrong struct.","solutions":["Ensure the Config field is populated (with Sequence and ChannelGroup) before calling Validate.","Re-serialize from the original bytes or rebuild the envelope if it came from an empty unmarshal.","Guard with a nil check on env.Config before invoking the validator."],"exampleFix":"// before\nenv := &cb.ConfigEnvelope{} // Config unset\nvalidator.Validate(env)\n// after\nenv := &cb.ConfigEnvelope{Config: &cb.Config{Sequence: seq, ChannelGroup: channelGroup}}\nvalidator.Validate(env)","handlingStrategy":"type-guard","validationCode":"if configEnv == nil || configEnv.Config == nil { return errors.New(\"config envelope has no inner Config\") }","typeGuard":"func hasConfig(cEnv *cb.ConfigEnvelope) bool { return cEnv != nil && cEnv.Config != nil }","tryCatchPattern":"if err := validator.Validate(env); err != nil {\n    if strings.Contains(err.Error(), \"config envelope has nil config\") {\n        // rebuild envelope with Config: &cb.Config{Sequence:..., ChannelGroup:...}\n        return err\n    }\n}","preventionTips":["Always set both Sequence and ChannelGroup on the inner Config","Check unmarshal results: an all-zero message means decoding failed","Construct envelopes with factory helpers rather than empty struct literals"],"tags":["hyperledger-fabric","configtx","nil-config","validation"],"backgroundTag":"nil-argument","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}