hyperledger/fabric · error

no instantiation policy was specified

Error message

no instantiation policy was specified

What it means

Security check 3 on deploy requires the ChaincodeData record produced by lscc to carry an InstantiationPolicy. A nil policy means the deployment record has no rule governing who may instantiate/upgrade the chaincode, so the validator rejects it rather than accepting an unprotected lifecycle record.

Source

Thrown at core/handlers/validation/builtin/v13/lscc_validation_logic.go:521

			if ac.PrivateChannelData() {
				// do extra validation for collections
				err := vscc.validateRWSetAndCollection(lsccrwset, cdRWSet, lsccArgs, lsccFunc, ac, chid)
				if err != nil {
					return err
				}
			} else {
				// there can only be a single ledger write
				if len(lsccrwset.Writes) != 1 {
					return policyErr(fmt.Errorf("LSCC can only issue a single putState upon deploy"))
				}
			}

			/*****************************************************/
			/* security check 3 - check the instantiation policy */
			/*****************************************************/
			pol := cdRWSet.InstantiationPolicy
			if pol == nil {
				return policyErr(fmt.Errorf("no instantiation policy was specified"))
			}
			// FIXME: could we actually pull the cds package from the
			// file system to verify whether the policy that is specified
			// here is the same as the one on disk?
			// PROS: we prevent attacks where the policy is replaced
			// CONS: this would be a point of non-determinism
			err := vscc.checkInstantiationPolicy(chid, env, pol, payl)
			if err != nil {
				return err
			}

		case lscc.UPGRADE:
			/**************************************************************/
			/* security check 1 - cc in the LCCC table of instantiated cc */
			/**************************************************************/
			if !ccExistsOnLedger {
				return policyErr(fmt.Errorf("Upgrading non-existent chaincode %s", cdsArgs.ChaincodeSpec.ChaincodeId.Name))
			}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Deploy through the standard flow (SDK instantiate or lifecycle tooling) so lscc generates and embeds an instantiation policy.
  2. If constructing ChaincodeData manually (tests), set InstantiationPolicy to a valid policy (e.g. SignedBy any MSP member).
  3. Verify the chaincode package and peer versions are consistent so policy serialization is preserved.
  4. Re-deploy the chaincode properly if the ledger record is missing its policy.

Example fix

// before
cd := &ccprovider.ChaincodeData{Name: name, Version: ver}
// after
cd := &ccprovider.ChaincodeData{Name: name, Version: ver, InstantiationPolicy: ipolBytes, ...}
Defensive patterns

Strategy: validation

Validate before calling

// before submit: ensure an instantiation policy is present
cd := &ccprovider.ChaincodeData{}
proto.Unmarshal(lsccWriteValue, cd)
if cd.InstantiationPolicy == nil {
    return errors.New("ChaincodeData has no instantiation policy")
}

Type guard

func hasInstantiationPolicy(cd *ccprovider.ChaincodeData) bool { return cd != nil && cd.InstantiationPolicy != nil }

Try / catch

if err != nil && strings.Contains(err.Error(), "no instantiation policy") { /* re-deploy via standard tooling so the policy is generated */ }

Prevention

When it happens

Trigger: A deploy transaction whose ChaincodeData has InstantiationPolicy == nil — typically from a hand-constructed ChaincodeData or a lscc variant that skipped policy generation.

Common situations: Custom tooling marshaling ChaincodeData without setting InstantiationPolicy, old chaincode packages built before policy fields were mandatory, test fixtures with minimal ChaincodeData structs, ledger records created by an older/patched peer.

Related errors


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