hyperledger/fabric · error

committing an invocation of cc %s is illegal

Error message

committing an invocation of cc %s is illegal

What it means

VSCC validation rejects any transaction that invokes a system chaincode which is not invokable externally (IsSysCCAndNotInvokableExternal). System chaincodes have no endorsement policy, so the validator has no way to decide validity for such invocations; it marks the tx ILLEGAL_WRITESET. Only externally invokable SCCs (like lscc, qscc, cscc) may be invoked through proposals.

Source

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

				VSCCName:  vscc.ChaincodeName,
			}
			if err = v.VSCCValidateTxForCC(ctx); err != nil {
				switch err.(type) {
				case *commonerrors.VSCCEndorsementPolicyError:
					return peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE, err
				default:
					return peer.TxValidationCode_INVALID_OTHER_REASON, err
				}
			}
		}
	} else {
		// make sure that we can invoke this system chaincode - if the chaincode
		// cannot be invoked through a proposal to this peer, we have to drop the
		// transaction; if we didn't, we wouldn't know how to decide whether it's
		// valid or not because in v1, system chaincodes have no endorsement policy
		if IsSysCCAndNotInvokableExternal(ccID) {
			return peer.TxValidationCode_ILLEGAL_WRITESET,
				errors.Errorf("committing an invocation of cc %s is illegal", ccID)
		}

		// Get latest chaincode version, vscc and validate policy
		_, vscc, policy, err := v.GetInfoForValidate(chdr, ccID)
		if err != nil {
			logger.Errorf("GetInfoForValidate for txId = %s returned error: %+v", chdr.TxId, err)
			return peer.TxValidationCode_INVALID_OTHER_REASON, err
		}

		// validate the transaction as an invocation of this system chaincode;
		// vscc will have to do custom validation for this system chaincode
		// currently, VSCC does custom validation for LSCC only; if an hlf
		// user creates a new system chaincode which is invokable from the outside
		// they have to modify VSCC to provide appropriate validation
		ctx := &Context{
			Seq:       seq,
			Envelope:  envBytes,
			Block:     block,

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Do not invoke internal system chaincodes via transactions; use the exposed, invokable ones (qscc, cscc, lscc) through the proper APIs
  2. If you authored a custom SCC, register it so IsSysCCAndNotInvokableExternal returns false only if it is safe to invoke externally
  3. Trace the transaction's ccID from the peer log and fix the client code sending the proposal
  4. Treat unexpected occurrences as potentially malicious input and review network access controls

Example fix

// before: invoking internal SCC directly
await channel.sendTransactionProposal({fcn: 'internalOp', chaincodeId: 'internalScc'});
// after: use the appropriate public SCC
const q = await channel.queryByChaincode({fcn: 'GetChainInfo', chaincodeId: 'qscc'});
Defensive patterns

Strategy: validation

Validate before calling

const invokableExternal = ['lscc','qscc','cscc'];
if (!invokableExternal.includes(chaincodeId)) throw new Error(`cc ${chaincodeId} is not invokable`);

Type guard

function isInvokableSysCC(ccId) {
  return ['lscc','qscc','cscc'].includes(ccId);
}

Try / catch

try { await send(proposal); } catch (e) {
  if (String(e).includes('committing an invocation of cc')) { console.error('targeted a non-invokable SCC'); }
}

Prevention

When it happens

Trigger: Dispatch to VSCCValidateTx where ccID (parsed from the header extension) names an internal system chaincode that is not registered as invokable external. Occurs when a proposal or transaction directly targets such an SCC.

Common situations: Crafted or buggy client proposals invoking internal SCCs; plugin/custom system chaincodes registered without external invokability; SDK misuse targeting internal chaincode names.

Related errors


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