hyperledger/fabric · error

bad type

Error message

bad type

What it means

ValidateUpdateConfigEnvelope only accepts envelopes whose ChannelHeader type is HeaderType_CONFIG_UPDATE. This error means the envelope is valid protobuf but of the wrong message type (e.g. ENDORSER_TRANSACTION, MESSAGE, CONFIG).

Source

Thrown at orderer/common/channelparticipation/validator.go:89

// It verifies it is an application channel by checking that the application group exists.
// It returns an error when it cannot be used as a update config envelope.
func ValidateUpdateConfigEnvelope(env *cb.Envelope) (channelID string, err error) {
	payload, err := protoutil.UnmarshalPayload(env.Payload)
	if err != nil {
		return "", errors.New("bad payload")
	}

	if payload.Header == nil || payload.Header.ChannelHeader == nil {
		return "", errors.New("bad header")
	}

	ch, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)
	if err != nil {
		return "", errors.New("could not unmarshall channel header")
	}

	if ch.Type != int32(cb.HeaderType_CONFIG_UPDATE) {
		return "", errors.New("bad type")
	}

	if ch.ChannelId == "" {
		return "", errors.New("empty channel id")
	}

	configUpdateEnv, err := protoutil.EnvelopeToConfigUpdate(env)
	if err != nil {
		return "", err
	}

	configUpdate, err := configtx.UnmarshalConfigUpdate(configUpdateEnv.ConfigUpdate)
	if err != nil {
		return "", err
	}

	return configUpdate.ChannelId, nil
}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Extract the ConfigUpdateEnvelope from the config block: read the block's CONFIG envelope and take its ConfigUpdate field, then wrap it as HeaderType_CONFIG_UPDATE.
  2. Use configtxlator (proto_decode / proto_encode between common.Config and ConfigUpdate) to build the correct envelope type.
  3. Check ch.Type before submitting: it must equal int32(cb.HeaderType_CONFIG_UPDATE) (value 2).
  4. Use the standard 'peer channel fetch config' + configtxlator + 'peer channel update' pipeline rather than raw block uploads.

Example fix

// before
env = configBlockEnv // header type CONFIG, not CONFIG_UPDATE
// after
cuEnv, _ := protoutil.CreateSignedEnvelope(cb.HeaderType_CONFIG_UPDATE, "mychannel", signer, configUpdate, 0, 0)
Defensive patterns

Strategy: validation

Validate before calling

hdr, _ := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)
if hdr.Type != int32(cb.HeaderType_CONFIG_UPDATE) {
    return fmt.Errorf("expected CONFIG_UPDATE envelope, got type %d", hdr.Type)
}

Type guard

func isConfigUpdateEnvelope(env *cb.Envelope) bool {
    p, err := protoutil.UnmarshalPayload(env.Payload)
    if err != nil || p.Header == nil || p.Header.ChannelHeader == nil { return false }
    ch, err := protoutil.UnmarshalChannelHeader(p.Header.ChannelHeader)
    return err == nil && ch.Type == int32(cb.HeaderType_CONFIG_UPDATE)
}

Try / catch

if _, err := ValidateUpdateConfigEnvelope(env); err != nil && strings.Contains(err.Error(), "bad type") {
    // rebuild via protoutil.CreateSignedEnvelope(cb.HeaderType_CONFIG_UPDATE, ...)
}

Prevention

When it happens

Trigger: Submitting a regular transaction envelope, a CONFIG envelope, or any non-CONFIG_UPDATE envelope to the channel participation join/update API.

Common situations: Confusing a config-update envelope with a full CONFIG envelope; accidentally uploading a computed config block instead of a ConfigUpdateEnvelope; script reusing a transaction envelope from a ledger fetch.

Related errors


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