hyperledger/fabric · error

Chaincode %s is already instantiated

Error message

Chaincode %s is already instantiated

What it means

On the lscc DEPLOY path, the validator checks whether the chaincode already exists on the ledger (ccExistsOnLedger). If it does, deploying it again is rejected because a chaincode with the same name can only be instantiated once per channel. Upgrades, not re-deploys, are the supported mechanism.

Source

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

			return policyErr(fmt.Errorf("expected cc version %s, found %s", cdsArgs.ChaincodeSpec.ChaincodeId.Version, cdRWSet.Version))
		}
		// it must only write to 2 namespaces: LSCC's and the cc that we are deploying/upgrading
		for _, ns := range txRWSet.NsRwSets {
			if ns.NameSpace != "lscc" && ns.NameSpace != cdRWSet.Name && len(ns.KvRwSet.Writes) > 0 {
				return policyErr(fmt.Errorf("LSCC invocation is attempting to write to namespace %s", ns.NameSpace))
			}
		}

		logger.Debugf("Validating %s for cc %s version %s", lsccFunc, cdRWSet.Name, cdRWSet.Version)

		switch lsccFunc {
		case lscc.DEPLOY:

			/******************************************************************/
			/* security check 1 - cc not in the LCCC table of instantiated cc */
			/******************************************************************/
			if ccExistsOnLedger {
				return policyErr(fmt.Errorf("Chaincode %s is already instantiated", cdsArgs.ChaincodeSpec.ChaincodeId.Name))
			}

			/****************************************************************************/
			/* security check 2 - validation of rwset (and of collections if enabled) */
			/****************************************************************************/
			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"))
				}
			}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Use upgrade instead of deploy if you want to change the chaincode version or policy.
  2. Query lscc (getchaincodes) or the ledger first to confirm the chaincode is not already instantiated before deploying.
  3. Make deployment scripts idempotent — skip deploy when the chaincode already exists on the channel.
  4. If a prior transaction actually committed, do not re-submit; check transaction status by txid.

Example fix

// before
client.invoke(new InstantiateProposalRequest...) // every run
// after
if (!lscc.getChaincodes().contains("mycc")) { client.invoke(instantiateReq); } else { client.invoke(upgradeReq); }
Defensive patterns

Strategy: validation

Validate before calling

// check before instantiating
resp, _ := lsccClient.Query("getchaincodes")
if chaincodeListContains(resp, "mycc") {
    return errors.New("mycc already instantiated; use upgrade instead of deploy")
}

Type guard

func isInstantiated(codes []lscc.ChaincodeQueryResponse, name string) bool {
    for _, c := range codes { if c.Name == name { return true } }
    return false
}

Try / catch

catch (err) { if (String(err).includes('already instantiated')) { /* switch to an upgrade request or treat as success if idempotent retry */ } }

Prevention

When it happens

Trigger: Issuing an lscc deploy (instantiation) for a chaincode name that already has a ChaincodeData record on the ledger — e.g. running instantiate twice, or re-running a deploy script after a partially failed upgrade.

Common situations: Retry logic re-submitting an instantiate proposal that actually succeeded, deployment automation without idempotency checks, attempting to change an already-instantiated chaincode via deploy instead of upgrade, restoring a ledger backup and replaying deploys.

Related errors


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