hyperledger/fabric · error
writeset contained key %s which did not appear in proposed c
Error message
writeset contained key %s which did not appear in proposed config
What it means
verifyFullProposedConfig found a key present in the update's writeSet that is absent from the fully computed proposed config. The delta application (computeUpdateResult) should produce a config containing every written key; if one is missing, the writeSet references a key that mapConfig/the update machinery cannot place in the resulting config, indicating a malformed or inconsistent update.
Source
Thrown at common/configtx/update.go:108
policy, ok := vi.policyForItem(existing)
if !ok {
return errors.Errorf("unexpected missing policy %s for item %s", existing.modPolicy(), key)
}
// Ensure the policy is satisfied
if err := policy.EvaluateSignedData(signedData); err != nil {
logger.Warnw("policy not satisfied for channel configuration update", "key", key, "policy", policy, "signingIdenties", protoutil.LogMessageForSerializedIdentities(signedData))
return errors.Wrapf(err, "policy for %s not satisfied", key)
}
}
return nil
}
func verifyFullProposedConfig(writeSet, fullProposedConfig map[string]comparable) error {
for key := range writeSet {
if _, ok := fullProposedConfig[key]; !ok {
return errors.Errorf("writeset contained key %s which did not appear in proposed config", key)
}
}
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 {View on GitHub (pinned to 2736b63f8f)
Solutions
- Regenerate the update from the actual current config using configtxlator (fetch config, decode, diff, encode) instead of hand-crafting the writeSet.
- Compare the writeSet keys against the current channel config tree to find the orphan key.
- Verify the update targets the same channel and was derived from that channel's latest config block.
- Remove the stray key from the writeSet if it is not a legitimate change.
Example fix
// before: hand-built writeSet with key "Groups/Orderer/Org1/OldKey" absent in proposed tree // after: diff current vs desired config via configtxlator so every writeSet key // appears in the recomputed full config config, _ := fetchAndDecodeChannelConfig(channelID) update := computeDiff(config, desiredConfig)
Defensive patterns
Strategy: validation
Validate before calling
// Every writeSet key must be resolvable in the config tree before proposing
func writeSetKeysResolvable(update *cb.ConfigUpdate) error {
for key := range update.GetWriteSet().GetValues() {
if key == "" { return fmt.Errorf("empty value key") }
}
for g := range update.GetWriteSet().GetGroups() {
if g == "" { return fmt.Errorf("empty group key") }
}
return nil
} Try / catch
if _, err := validator.ProposeConfigUpdate(env, seq); err != nil {
if strings.Contains(err.Error(), "did not appear in proposed config") {
// rebuild update via configtxlator diff from current config
}
return err
} Prevention
- Always generate the writeSet as a diff of the fetched current config vs desired config.
- Never hand-craft writeSet keys; mirror the group/value/policy hierarchy exactly.
- Tag update files with the channel and config sequence they were derived from.
When it happens
Trigger: Calling proposeConfigUpdate/Validate with a writeSet key that computeUpdateResult dropped — e.g. a key whose namespace/group mapping fails, or a delta applied to a path that does not exist in the full proposed config.
Common situations: Constructing a ConfigUpdate programmatically with keys not matching the config tree structure; using an update file generated against a different channel or config version; corrupted/partially serialized write-set after manual proto editing.
Related errors
- error mapping WriteSet
- full config did not verify
- 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
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/a5aff3dc7756a2c7.
Report an issue: GitHub.