hyperledger/fabric · error

full config did not verify

Error message

full config did not verify

What it means

After policy verification, the fully computed proposed config failed verifyFullProposedConfig — some writeSet key is missing from the resulting full config. This wraps error 152 and indicates the update, though policy-authorized, produces an inconsistent result: the written key cannot be located in the recomputed config tree.

Source

Thrown at common/configtx/update.go:156

	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)
	if err != nil {
		return nil, err
	}

	if err = vi.verifyDeltaSet(deltaSet, signedData); err != nil {
		return nil, errors.Wrapf(err, "error validating DeltaSet")
	}

	fullProposedConfig := vi.computeUpdateResult(deltaSet)
	if err := verifyFullProposedConfig(writeSet, fullProposedConfig); err != nil {
		return nil, errors.Wrapf(err, "full config did not verify")
	}

	return fullProposedConfig, nil
}

func (vi *ValidatorImpl) policyForItem(item comparable) (policies.Policy, bool) {
	manager := vi.pm

	modPolicy := item.modPolicy()
	logger.Debugf("Getting policy for item %s with mod_policy %s", item.key, modPolicy)

	// If the mod_policy path is relative, get the right manager for the context
	// If the item has a zero length path, it is the root group, use the base policy manager
	// if the mod_policy path is absolute (starts with /) also use the base policy manager
	if len(modPolicy) > 0 && modPolicy[0] != policies.PathSeparator[0] && len(item.path) != 0 {
		var ok bool

		manager, ok = manager.Manager(item.path[1:])

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Regenerate the update via configtxlator diff from the current config to guarantee writeSet keys map into the full config.
  2. Compare writeSet key paths against the config tree and fix paths that don't correspond to any group/value/policy position.
  3. Confirm the update was derived from the target channel's current config.
  4. Remove writeSet keys that are not legitimate intended changes.

Example fix

// before: writeSet key "Channel/Group/Value" (flat path) not reproducible
// after: place it correctly: groups.Channel.groups.Group.values.Value
update.WriteSet.Groups["Application"].Values["BatchSize"] = ...
Defensive patterns

Strategy: validation

Validate before calling

// Simulate: every writeSet key must exist in the recomputed config result
func keysInResult(writeSet *cb.ConfigGroup, result map[string]interface{}) error {
    // iterate writeSet keys and assert presence in computeUpdateResult output
    return verifyWriteKeysPresent(writeSet, result)
}

Try / catch

if _, err := validator.ProposeConfigUpdate(env, seq); err != nil {
    if strings.Contains(err.Error(), "full config did not verify") {
        // rebuild the update as a proper diff of the live config
    }
    return err
}

Prevention

When it happens

Trigger: Calling proposeConfigUpdate/Validate where the delta applied by computeUpdateResult yields a full config lacking a writeSet key — malformed writeSet paths or keys not derivable from the config structure.

Common situations: Programmatically constructed updates with paths that don't mirror the config hierarchy; updates built from a different channel's config; manual proto edits that break key naming.

Related errors


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