hyperledger/fabric · error
invalid config envelope
Error message
invalid config envelope
What it means
ValidateConfig hands the config envelope to verifyConfigUpdateMsg, which requires the envelope to contain a LastUpdate and a Config. A nil/empty ConfigEnvelope means the block being validated does not actually carry a usable config, so validation fails immediately.
Source
Thrown at orderer/consensus/smartbft/configverifier.go:194
if err := proto.Unmarshal(consensusTypeConfigValue.Value, consensusTypeValue); err != nil {
return fmt.Errorf("invalid consensus type property in config: %v", err)
}
configOptions := &smartbft.Options{}
if err := proto.Unmarshal(consensusTypeValue.Metadata, configOptions); err != nil {
return fmt.Errorf("invalid options encoded in consensus metadata: %v", err)
}
if configOptions.LeaderRotation == smartbft.Options_ROTATION_ON {
return fmt.Errorf("leader rotation must be turned off for this version or be unspecified")
}
return nil
}
func (cbv *ConfigBlockValidator) verifyConfigUpdateMsg(outEnv *common.Envelope, confEnv *common.ConfigEnvelope, chdr *common.ChannelHeader) error {
if confEnv == nil || confEnv.LastUpdate == nil || confEnv.Config == nil {
return errors.New("invalid config envelope")
}
envPayload, err := protoutil.UnmarshalPayload(confEnv.LastUpdate.Payload)
if err != nil {
return err
}
if envPayload.Header == nil {
return errors.New("inner header is nil")
}
if envPayload.Header.ChannelHeader == nil {
return errors.New("inner channelheader is nil")
}
typ := common.HeaderType(chdr.Type)
cbv.Logger.Infof("Applying filters for config update of type %s to channel %s", typ, chdr.ChannelId)
View on GitHub (pinned to 2736b63f8f)
Solutions
- Ensure the config transaction envelope contains a proper ConfigUpdateEnvelope as LastUpdate and a computed Config
- Rebuild the config submission using the standard config update flow (fetch current config, compute update, sign, submit)
- Inspect the block payload to confirm the ConfigEnvelope fields are populated before submitting
Example fix
// before
env := &common.ConfigEnvelope{Config: cfg} // LastUpdate missing
// after
env := &common.ConfigEnvelope{Config: cfg, LastUpdate: signedConfigUpdateEnvelope} Defensive patterns
Strategy: type-guard
Validate before calling
if confEnv == nil || confEnv.LastUpdate == nil || confEnv.Config == nil {
return errors.New("config envelope incomplete: need Config and LastUpdate")
} Type guard
func validConfigEnvelope(confEnv *common.ConfigEnvelope) bool {
return confEnv != nil && confEnv.LastUpdate != nil && confEnv.Config != nil
} Prevention
- Assemble config transactions only through the standard update flow
- Validate envelope completeness before broadcast
- Never submit empty or partially built CONFIG blocks
When it happens
Trigger: verifyConfigUpdateMsg called with confEnv == nil, confEnv.LastUpdate == nil, or confEnv.Config == nil — i.e. the ConfigEnvelope extracted from the block is incomplete.
Common situations: Submitting a malformed config transaction whose payload lacks the config update; a block containing a truncated or empty config envelope; custom clients sending CONFIG transactions with wrong inner structure.
Related errors
- inner header is nil
- inner channelheader is nil
- error extracting channel ID from config update
- consenter options type mismatch
- channel header not found in the envelope
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/e33e5e00fe54161e.
Report an issue: GitHub.