hyperledger/fabric · error

nil ChaincodeId in ChaincodeAction

Error message

nil ChaincodeId in ChaincodeAction

What it means

Companion check to the header extension: the ChaincodeAction's response payload (RespPayload.ChaincodeId) is nil, so the dispatcher cannot determine the chaincode name/version that produced the results. The transaction is rejected with INVALID_OTHER_REASON because the rwset cannot be attributed to a chaincode for policy validation.

Source

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

	}

	/* obtain the list of namespaces we're writing to */
	respPayload, err := protoutil.GetActionFromEnvelope(envBytes)
	if err != nil {
		return peer.TxValidationCode_BAD_RESPONSE_PAYLOAD, errors.WithMessage(err, "GetActionFromEnvelope failed")
	}
	txRWSet := &rwsetutil.TxRwSet{}
	if err = txRWSet.FromProtoBytes(respPayload.Results); err != nil {
		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

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Fix the client SDK so proposal response payloads embed the ChaincodeId correctly
  2. Inspect the offending transaction envelope to find where the payload was dropped/corrupted
  3. Harden the network against tampering (TLS, honest endorsers) and re-submit a fresh transaction
  4. Update to patched Fabric/SDK versions if a serialization bug is responsible

Example fix

// before: payload built without ChaincodeId
const respPayload = new ChaincodeAction({results: rwsetBytes});
// after
const respPayload = new ChaincodeAction({results: rwsetBytes, chaincodeId: {name: 'mycc', version: '1.0'}});
Defensive patterns

Strategy: type-guard

Validate before calling

// verify endorsement response payload before assembling the transaction
if (!respPayload.chaincodeId || !respPayload.chaincodeId.name) throw new Error('missing ChaincodeId in ChaincodeAction');

Type guard

function hasRespChaincodeId(respPayload) {
  return !!respPayload && !!respPayload.chaincodeId && !!respPayload.chaincodeId.name && !!respPayload.chaincodeId.version;
}

Try / catch

try { await channel.sendTransaction(tx); } catch (e) {
  if (String(e).includes('nil ChaincodeId in ChaincodeAction')) { /* discard tx, obtain fresh endorsements */ }
}

Prevention

When it happens

Trigger: Dispatch validates a transaction where hdrExt.ChaincodeId is present but respPayload.ChaincodeId (from the proposal response payload inside the ChaincodeAction) is nil — typically a tampered, corrupted, or wrongly assembled proposal response payload.

Common situations: Malicious transaction crafting; SDK assembling proposal responses incorrectly; corrupted payloads introduced between endorsement and commit.

Related errors


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