hyperledger/fabric · error

chaincode id is nil

Error message

chaincode id is nil

What it means

After confirming ChaincodeSpec is non-nil, InvokedChaincodeName also requires ChaincodeSpec.ChaincodeId to be set, since the chaincode name is read from ChaincodeId.Name. A spec without a ChaincodeId cannot name the target chaincode, so this error is returned.

Source

Thrown at protoutil/proputils.go:435

	proposalPayload := &peer.ChaincodeProposalPayload{}
	err = proto.Unmarshal(proposal.Payload, proposalPayload)
	if err != nil {
		return "", errors.WithMessage(err, "could not unmarshal chaincode proposal payload")
	}

	cis := &peer.ChaincodeInvocationSpec{}
	err = proto.Unmarshal(proposalPayload.Input, cis)
	if err != nil {
		return "", errors.WithMessage(err, "could not unmarshal chaincode invocation spec")
	}

	if cis.ChaincodeSpec == nil {
		return "", errors.Errorf("chaincode spec is nil")
	}

	if cis.ChaincodeSpec.ChaincodeId == nil {
		return "", errors.Errorf("chaincode id is nil")
	}

	return cis.ChaincodeSpec.ChaincodeId.Name, nil
}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Set ChaincodeSpec.ChaincodeId (at minimum the Name field) when constructing the ChaincodeInvocationSpec.
  2. Ensure the proposal builder in your client passes the chaincode name (and version/path where applicable) into the ChaincodeID.
  3. For on-chain proposals received from peers, reject malformed ones and require the submitting client to resend a correctly built proposal.
  4. When converting from legacy formats, map old spec fields into the new ChaincodeID explicitly instead of relying on defaults.

Example fix

// before
cs := &peer.ChaincodeSpec{Type: peer.ChaincodeSpec_GOLANG, Input: ci}

// after
cs := &peer.ChaincodeSpec{
    Type:        peer.ChaincodeSpec_GOLANG,
    ChaincodeId: &peer.ChaincodeID{Name: "mycc", Version: "v1"},
    Input:       ci,
}
Defensive patterns

Strategy: validation

Validate before calling

if cis.ChaincodeSpec == nil || cis.ChaincodeSpec.ChaincodeId == nil || cis.ChaincodeSpec.ChaincodeId.Name == "" {
    return errors.New("invoke proposal must carry a chaincode id with a name")
}

Type guard

func hasChaincodeID(cs *peer.ChaincodeSpec) bool {
    return cs != nil && cs.ChaincodeId != nil && cs.ChaincodeId.Name != ""
}

Try / catch

name, err := protoutil.InvokedChaincodeName(signedProp)
if err != nil {
    httpStatus = codes.InvalidArgument
    return fmt.Errorf("proposal missing chaincode id: %w", err)
}

Prevention

When it happens

Trigger: A ChaincodeInvocationSpec whose ChaincodeSpec exists but has a nil ChaincodeId reaches InvokedChaincodeName — proposals built with only Type/Input set, or specs deserialized from bytes missing the chaincode_id field.

Common situations: Hand-built proposals missing the ChaincodeID; older/other-version SDKs emitting specs where the id field was dropped; SystemCC or constructor paths that set input args without a chaincode id.

Related errors


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