hyperledger/fabric · error

invalid chaincode ID

Error message

invalid chaincode ID

What it means

Dispatch validates the chaincode action extracted from a transaction's response payload. The header extension's ChaincodeId.Name (ccID) is empty, meaning the transaction proposal header did not carry a chaincode name, so the tx is marked INVALID_CHAINCODE. Fabric throws this as part of the V20 validator's sanity checks before executing validation plugins.

Source

Thrown at core/committer/txvalidator/v20/plugindispatcher/dispatcher.go:143

		return peer.TxValidationCode_BAD_RWSET, errors.WithMessage(err, "txRWSet.FromProtoBytes failed")
	}

	// Verify the header extension and response payload contain the ChaincodeId
	if hdrExt.ChaincodeId == nil {
		return peer.TxValidationCode_INVALID_OTHER_REASON, errors.New("nil ChaincodeId in header extension")
	}

	if respPayload.ChaincodeId == nil {
		return peer.TxValidationCode_INVALID_OTHER_REASON, errors.New("nil ChaincodeId in ChaincodeAction")
	}

	// get name and version of the cc we invoked
	ccID := hdrExt.ChaincodeId.Name
	ccVer := respPayload.ChaincodeId.Version

	// sanity check on ccID
	if ccID == "" {
		err = errors.New("invalid chaincode ID")
		logger.Errorf("%+v", err)
		return peer.TxValidationCode_INVALID_CHAINCODE, err
	}
	if ccID != respPayload.ChaincodeId.Name {
		err = errors.Errorf("inconsistent ccid info (%s/%s)", ccID, respPayload.ChaincodeId.Name)
		logger.Errorf("%+v", err)
		return peer.TxValidationCode_INVALID_CHAINCODE, err
	}
	// sanity check on ccver
	if ccVer == "" {
		err = errors.New("invalid chaincode version")
		logger.Errorf("%+v", err)
		return peer.TxValidationCode_INVALID_CHAINCODE, err
	}

	wrNamespace := map[string]bool{}
	wrNamespace[ccID] = true
	if respPayload.Events != nil {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Fix the client invocation so ChaincodeHeaderExtension.ChaincodeId.Name is always set (pass chaincodeId to the SDK proposal request).
  2. Regenerate the transaction/envelope instead of reusing old serialized ones (replay of stale or hand-crafted payloads).
  3. Verify SDK and peer versions are compatible (header extension proto layout changed across Fabric versions).
  4. Inspect the offending tx with the peer to confirm the proposal header; treat as malicious/corrupt if produced by a third party.
  5. If a custom validation plugin is involved, ensure it does not feed payloads with empty ChaincodeId into Dispatch.

Example fix

// before (client SDK)
const request = { fcn: 'invoke', args: ['a','b','1'] };
// after
const request = { chaincodeId: 'mycc', fcn: 'invoke', args: ['a','b','1'] };
Defensive patterns

Strategy: validation

Validate before calling

if (!request.chaincodeId || request.chaincodeId.length === 0) { throw new Error('chaincodeId must be set on the invocation request'); }

Type guard

function hasChaincodeId(req) { return typeof req.chaincodeId === 'string' && req.chaincodeId.length > 0; }

Try / catch

try { await contract.submitTransaction(...); } catch (err) { if (/invalid chaincode ID/.test(err.message)) { /* fix chaincodeId on request and retry */ } else { throw err; } }

Prevention

When it happens

Trigger: DispatchToPlugin/Dispatch is called during commit-time validation and hdrExt.ChaincodeId.Name is empty — e.g. a malformed ChaincodeHeaderExtension, a tampered or corrupted payload, or a chaincode invocation built without the chaincode ID field in the proposal header.

Common situations: Buggy custom client SDK invocations that omit chaincodeId; manually crafted or corrupted envelopes (replayed/attacked txs); mixing peer/SDK versions so header extension fields are not populated; using the default validator to validate transactions produced by incompatible tooling.

Related errors


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