hyperledger/fabric · critical

chaincode definition for [%s] is invalid, plugin field must

Error message

chaincode definition for [%s] is invalid, plugin field must be set

What it means

getCDataForCC (invoked via GetInfoForValidate during validation) fetched the chaincode definition from the lifecycle/LSCC, and its validation-plugin field is empty. Since V20 validation requires every chaincode definition to name a validation plugin (default 'vscc'), Fabric returns this error meaning the definition on the ledger is incomplete or was written without required fields.

Source

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

func (v *dispatcherImpl) getCDataForCC(channelID, ccid string) (string, []byte, error) {
	qe, err := v.ler.NewQueryExecutor()
	if err != nil {
		return "", nil, errors.WithMessage(err, "could not retrieve QueryExecutor")
	}
	defer qe.Done()

	plugin, args, unexpectedErr, validationErr := v.lcr.ValidationInfo(channelID, ccid, qe)
	if unexpectedErr != nil {
		return "", nil, &commonerrors.VSCCInfoLookupFailureError{
			Reason: fmt.Sprintf("Could not retrieve state for chaincode %s, error %s", ccid, unexpectedErr),
		}
	}
	if validationErr != nil {
		return "", nil, validationErr
	}

	if plugin == "" {
		return "", nil, errors.Errorf("chaincode definition for [%s] is invalid, plugin field must be set", ccid)
	}

	if len(args) == 0 {
		return "", nil, errors.Errorf("chaincode definition for [%s] is invalid, policy field must be set", ccid)
	}

	return plugin, args, nil
}

// GetInfoForValidate gets the ChaincodeInstance(with latest version) of tx, validation plugin and policy
func (v *dispatcherImpl) GetInfoForValidate(chdr *common.ChannelHeader, ccID string) (string, []byte, error) {
	// obtain name of the validation plugin and the policy
	plugin, args, err := v.getCDataForCC(chdr.ChannelId, ccID)
	if err != nil {
		logger.Errorf("Unable to get chaincode data from ledger for txid %s, due to %s", chdr.TxId, err)
		return "", nil, err
	}
	return plugin, args, nil

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Set the plugin field explicitly (use default 'vscc' for endorsement-policy validation) in the chaincode definition and re-approve/upgrade.
  2. Re-issue the chaincode definition transaction with all required fields populated.
  3. Fix the lifecycle code that persisted the definition so it defaults plugin to 'vscc' when unset.
  4. Restore the definition from a healthy backup/orderer snapshot if ledger data is corrupt.

Example fix

// before (definition JSON)
{ "Name":"mycc", "Version":"1.0", "Policy": ... }  // plugin missing
// after
{ "Name":"mycc", "Version":"1.0", "Plugin":"vscc", "Policy": ... }
Defensive patterns

Strategy: validation

Validate before calling

const def = getChaincodeDefinition(name, version); if (!def.plugin) throw new Error(`definition for ${name} missing plugin; expected 'vscc' or custom plugin`);

Type guard

function hasPlugin(def) { return typeof def?.plugin === 'string' && def.plugin.length > 0; }

Try / catch

try { getInfoForValidate(); } catch (err) { if (/plugin field must be set/.test(err.message)) { /* re-issue definition with plugin set */ } else { throw err; } }

Prevention

When it happens

Trigger: Chaincode definition stored on-chain (via LCCS JSON args or new lifecycle) has an empty plugin name when Dispatch→GetInfoForValidate→getCDataForCC reads it — e.g. an LSCC record hand-written with missing plugin field, or a corrupted/incomplete upgrade.

Common situations: Manually edited or legacy LSCC records migrated from older networks without the plugin field; failed/partial chaincode upgrades leaving incomplete definitions; custom lifecycle implementations that skip plugin defaults.

Related errors


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