hyperledger/fabric · error

duplicate namespace '%s' in txRWSet

Error message

duplicate namespace '%s' in txRWSet

What it means

The transaction's read-write set (TxRwSet) contains two NsRwSets with the same NameSpace. VSCC rejects this as TxValidationCode_ILLEGAL_WRITESET because a well-formed rwset produced by the peer must have unique namespaces; duplicates indicate a tampered or malformed write set.

Source

Thrown at core/committer/txvalidator/v14/vscc_validator.go:136

	alwaysEnforceOriginalNamespace := v.cr.Capabilities().V1_2Validation()
	if alwaysEnforceOriginalNamespace {
		wrNamespace = append(wrNamespace, ccID)
		if respPayload.Events != nil {
			ccEvent := &peer.ChaincodeEvent{}
			if err = proto.Unmarshal(respPayload.Events, ccEvent); err != nil {
				return peer.TxValidationCode_INVALID_OTHER_REASON, errors.Wrapf(err, "invalid chaincode event")
			}
			if ccEvent.ChaincodeId != ccID {
				return peer.TxValidationCode_INVALID_OTHER_REASON, errors.Errorf("chaincode event chaincode id does not match chaincode action chaincode id")
			}
		}
	}

	namespaces := make(map[string]struct{})
	for _, ns := range txRWSet.NsRwSets {
		// check to make sure there is no duplicate namespace in txRWSet
		if _, ok := namespaces[ns.NameSpace]; ok {
			return peer.TxValidationCode_ILLEGAL_WRITESET, errors.Errorf("duplicate namespace '%s' in txRWSet", ns.NameSpace)
		}
		namespaces[ns.NameSpace] = struct{}{}

		if !v.txWritesToNamespace(ns) {
			continue
		}

		// Check to make sure we did not already populate this chaincode
		// name to avoid checking the same namespace twice
		if ns.NameSpace != ccID || !alwaysEnforceOriginalNamespace {
			wrNamespace = append(wrNamespace, ns.NameSpace)
		}

		if !writesToLSCC && ns.NameSpace == "lscc" {
			writesToLSCC = true
		}

		if !writesToNonInvokableSCC && IsSysCCAndNotInvokableCC2CC(ns.NameSpace) {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure the rwset comes from real endorsement execution by the peer rather than being assembled or merged client-side.
  2. If merging rwsets is unavoidable, deduplicate NsRwSets by NameSpace before submission.
  3. Investigate the submitting client for rwset tampering if duplicates appear without custom tooling.

Example fix

// before: append both rwsets
allNs := append(rwsetA.NsRwSets, rwsetB.NsRwSets...)
// after: dedupe by namespace
seen := map[string]bool{}
for _, ns := range allNs { if seen[ns.NameSpace] { continue }; seen[ns.NameSpace] = true; out = append(out, ns) }
Defensive patterns

Strategy: validation

Validate before calling

seen := map[string]struct{}{}
for _, ns := range txRWSet.NsRwSets {
    if _, dup := seen[ns.NameSpace]; dup {
        return fmt.Errorf("duplicate namespace %q in rwset; rebuild transaction", ns.NameSpace)
    }
    seen[ns.NameSpace] = struct{}{}
}

Type guard

func namespacesUnique(rwset *rwset.TxRwSet) bool {
	seen := map[string]struct{}{}
	for _, ns := range rwset.NsRwSets {
		if _, ok := seen[ns.NameSpace]; ok {
			return false
		}
		seen[ns.NameSpace] = struct{}{}
	}
	return true
}

Try / catch

if err != nil {
    return peer.TxValidationCode_ILLEGAL_WRITESET, errors.Errorf("duplicate namespace '%s' in txRWSet", ns.NameSpace)
}

Prevention

When it happens

Trigger: A transaction whose Results bytes in the ChaincodeAction decode to a TxRwSet with repeated namespace entries — produced by custom rwset assembly, merging of rwsets without deduplication, or malicious construction.

Common situations: Offline endorsement / custom rwset-building tools concatenating per-chaincode rwsets; chaincode-side or middleware-side rwset manipulation; corruption in crafted transactions for testing.

Related errors


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