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

  1. Ensure the config transaction envelope contains a proper ConfigUpdateEnvelope as LastUpdate and a computed Config
  2. Rebuild the config submission using the standard config update flow (fetch current config, compute update, sign, submit)
  3. 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

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


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/e33e5e00fe54161e. Report an issue: GitHub.