{"record":{"id":"9412b32015ef115f","repo":"hyperledger/fabric","slug":"committing-an-invocation-of-cc-s-is-illegal","errorCode":null,"errorMessage":"committing an invocation of cc %s is illegal","messagePattern":"committing an invocation of cc (.+?) is illegal","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/committer/txvalidator/v14/vscc_validator.go","lineNumber":236,"sourceCode":"\t\t\t\tVSCCName:  vscc.ChaincodeName,\n\t\t\t}\n\t\t\tif err = v.VSCCValidateTxForCC(ctx); err != nil {\n\t\t\t\tswitch err.(type) {\n\t\t\t\tcase *commonerrors.VSCCEndorsementPolicyError:\n\t\t\t\t\treturn peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE, err\n\t\t\t\tdefault:\n\t\t\t\t\treturn peer.TxValidationCode_INVALID_OTHER_REASON, err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// make sure that we can invoke this system chaincode - if the chaincode\n\t\t// cannot be invoked through a proposal to this peer, we have to drop the\n\t\t// transaction; if we didn't, we wouldn't know how to decide whether it's\n\t\t// valid or not because in v1, system chaincodes have no endorsement policy\n\t\tif IsSysCCAndNotInvokableExternal(ccID) {\n\t\t\treturn peer.TxValidationCode_ILLEGAL_WRITESET,\n\t\t\t\terrors.Errorf(\"committing an invocation of cc %s is illegal\", ccID)\n\t\t}\n\n\t\t// Get latest chaincode version, vscc and validate policy\n\t\t_, vscc, policy, err := v.GetInfoForValidate(chdr, ccID)\n\t\tif err != nil {\n\t\t\tlogger.Errorf(\"GetInfoForValidate for txId = %s returned error: %+v\", chdr.TxId, err)\n\t\t\treturn peer.TxValidationCode_INVALID_OTHER_REASON, err\n\t\t}\n\n\t\t// validate the transaction as an invocation of this system chaincode;\n\t\t// vscc will have to do custom validation for this system chaincode\n\t\t// currently, VSCC does custom validation for LSCC only; if an hlf\n\t\t// user creates a new system chaincode which is invokable from the outside\n\t\t// they have to modify VSCC to provide appropriate validation\n\t\tctx := &Context{\n\t\t\tSeq:       seq,\n\t\t\tEnvelope:  envBytes,\n\t\t\tBlock:     block,","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/committer/txvalidator/v14/vscc_validator.go#L218-L254","documentation":"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.","triggerScenarios":"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.","commonSituations":"Crafted or buggy client proposals invoking internal SCCs; plugin/custom system chaincodes registered without external invokability; SDK misuse targeting internal chaincode names.","solutions":["Do not invoke internal system chaincodes via transactions; use the exposed, invokable ones (qscc, cscc, lscc) through the proper APIs","If you authored a custom SCC, register it so IsSysCCAndNotInvokableExternal returns false only if it is safe to invoke externally","Trace the transaction's ccID from the peer log and fix the client code sending the proposal","Treat unexpected occurrences as potentially malicious input and review network access controls"],"exampleFix":"// before: invoking internal SCC directly\nawait channel.sendTransactionProposal({fcn: 'internalOp', chaincodeId: 'internalScc'});\n// after: use the appropriate public SCC\nconst q = await channel.queryByChaincode({fcn: 'GetChainInfo', chaincodeId: 'qscc'});","handlingStrategy":"validation","validationCode":"const invokableExternal = ['lscc','qscc','cscc'];\nif (!invokableExternal.includes(chaincodeId)) throw new Error(`cc ${chaincodeId} is not invokable`);","typeGuard":"function isInvokableSysCC(ccId) {\n  return ['lscc','qscc','cscc'].includes(ccId);\n}","tryCatchPattern":"try { await send(proposal); } catch (e) {\n  if (String(e).includes('committing an invocation of cc')) { console.error('targeted a non-invokable SCC'); }\n}","preventionTips":["Only target whitelisted SCCs from clients","Verify chaincodeId in proposal construction","Treat repeated occurrences as potential attacks"],"tags":["hyperledger-fabric","system-chaincode","tx-validation","illegal-invocation"],"backgroundTag":"illegal-scc-invocation","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}