hyperledger/fabric · error
ConfigUpdate for channel '%s' but envelope for channel '%s'
Error message
ConfigUpdate for channel '%s' but envelope for channel '%s'
What it means
The channel ID inside the ConfigUpdate does not match the channel this validator was created for. An update envelope is only valid for its intended channel; a mismatch means the envelope was built for, or is being validated against, the wrong channel.
Source
Thrown at common/configtx/update.go:127
}
}
return nil
}
// authorizeUpdate validates that all modified config has the corresponding modification policies satisfied by the signature set
// it returns a map of the modified config
func (vi *ValidatorImpl) authorizeUpdate(configUpdateEnv *cb.ConfigUpdateEnvelope) (map[string]comparable, error) {
if configUpdateEnv == nil {
return nil, errors.Errorf("cannot process nil ConfigUpdateEnvelope")
}
configUpdate, err := UnmarshalConfigUpdate(configUpdateEnv.ConfigUpdate)
if err != nil {
return nil, err
}
if configUpdate.ChannelId != vi.channelID {
return nil, errors.Errorf("ConfigUpdate for channel '%s' but envelope for channel '%s'", configUpdate.ChannelId, vi.channelID)
}
readSet, err := mapConfig(configUpdate.ReadSet, vi.namespace)
if err != nil {
return nil, errors.Wrapf(err, "error mapping ReadSet")
}
err = vi.verifyReadSet(readSet)
if err != nil {
return nil, errors.Wrapf(err, "error validating ReadSet")
}
writeSet, err := mapConfig(configUpdate.WriteSet, vi.namespace)
if err != nil {
return nil, errors.Wrapf(err, "error mapping WriteSet")
}
deltaSet := computeDeltaSet(readSet, writeSet)
signedData, err := protoutil.ConfigUpdateEnvelopeAsSignedData(configUpdateEnv)View on GitHub (pinned to 2736b63f8f)
Solutions
- Regenerate the update with the correct channel_id matching the target channel (configtxlator / configtxgen -channelID).
- Verify you are submitting the update transaction to the intended channel (peer channel update -c <channel>).
- Re-fetch the current config from the correct channel and rebuild the diff.
Example fix
// before
{"channel_id": "channel-a", ...}
// after
{"channel_id": "mychannel", ...} Defensive patterns
Strategy: validation
Validate before calling
// Confirm the update's channel matches the target before submitting
func checkChannel(update *cb.ConfigUpdate, channelID string) error {
if update.GetChannelId() != channelID {
return fmt.Errorf("update targets %q, expected %q", update.GetChannelId(), channelID)
}
return nil
} Try / catch
if _, err := validator.ProposeConfigUpdate(env, seq); err != nil {
if strings.Contains(err.Error(), "but envelope for channel") {
// rebuild update for the correct channel before retry
}
return err
} Prevention
- Parameterize scripts by channel name; never hardcode channel IDs from examples.
- Fetch the base config from the same channel the update is submitted to.
- Store update files named by channel (e.g. mychannel-update.pb) to avoid mixups.
- Print the ConfigUpdate channel_id in CI before submission.
When it happens
Trigger: Calling proposeConfigUpdate/Validate with a ConfigUpdateEnvelope whose ConfigUpdate.channel_id differs from vi.channelID — e.g. submitting an update generated for channel A to the validator of channel B.
Common situations: Mixing up update files when operating multiple channels; copying an example update and forgetting to change channel_id; using a fetched config from one channel to build an update submitted to another.
Related errors
- Attempted to set the batch size max message count to an inva
- Attempted to set the batch size absolute max bytes to an inv
- Attempted to set the batch size preferred max bytes to an in
- Attempted to set the batch size preferred max bytes (%v) gre
- Attempted to set the batch timeout to a invalid value: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/f5b00e0e612e7530.
Report an issue: GitHub.