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
- Set ChaincodeSpec.ChaincodeId (at minimum the Name field) when constructing the ChaincodeInvocationSpec.
- Ensure the proposal builder in your client passes the chaincode name (and version/path where applicable) into the ChaincodeID.
- For on-chain proposals received from peers, reject malformed ones and require the submitting client to resend a correctly built proposal.
- 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
- Always set peer.ChaincodeID{Name: ...} when building a ChaincodeSpec.
- For system chaincode calls, set the well-known system CC name explicitly.
- Validate proposals client-side (name non-empty) before signing.
- When migrating from legacy proposal formats, map the chaincode id field explicitly.
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
- chaincode spec is nil
- cannot create proposal, due to %s
- Cannot create proposal, due to %s
- no chaincode name is provided, channel id [%s]
- empty block data
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/b53e8bec31621209.
Report an issue: GitHub.