hyperledger/fabric · error
unexpected chaincode type: %s
Error message
unexpected chaincode type: %s
What it means
During system chaincode upgrade validation, the deployed chaincode's ChaincodeDeploymentSpec must be a GOLANG spec. Any other chaincode language type is rejected because legacy system chaincode upgrades only support Go chaincode.
Source
Thrown at core/committer/txvalidator/v14/validator.go:593
upgradeIns, err := v.getUpgradeTxInstance(channelID, cis.ChaincodeSpec.Input.Args[2])
if err != nil {
return invokeIns, nil, nil
}
return invokeIns, upgradeIns, nil
}
}
return invokeIns, nil, nil
}
func (v *TxValidator) getUpgradeTxInstance(channelID string, cdsBytes []byte) (*sysccprovider.ChaincodeInstance, error) {
cds, err := protoutil.UnmarshalChaincodeDeploymentSpec(cdsBytes)
if err != nil {
return nil, err
}
if cds.ChaincodeSpec.Type.String() != "GOLANG" {
return nil, errors.Errorf("unexpected chaincode type: %s", cds.ChaincodeSpec.Type.String())
}
return &sysccprovider.ChaincodeInstance{
ChannelID: channelID,
ChaincodeName: cds.ChaincodeSpec.ChaincodeId.Name,
ChaincodeVersion: cds.ChaincodeSpec.ChaincodeId.Version,
}, nil
}
type dynamicDeserializer struct {
cr ChannelResources
}
func (ds *dynamicDeserializer) DeserializeIdentity(serializedIdentity []byte) (msp.Identity, error) {
return ds.cr.MSPManager().DeserializeIdentity(serializedIdentity)
}
func (ds *dynamicDeserializer) IsWellFormed(identity *mspprotos.SerializedIdentity) error {View on GitHub (pinned to 2736b63f8f)
Solutions
- Rebuild the upgrade transaction with a GOLANG ChaincodeSpec type
- Verify the tooling/SDK generating the spec sets ChaincodeSpec.Type to GOLANG
- If this comes from a block being validated, treat the transaction as invalid and exclude it; do not attempt to commit it
- Check whether the upgrade is even required — most system chaincode upgrades are peer-managed, not via transactions
Example fix
// before
spec := &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_NODE, ...}
// after
spec := &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_GOLANG, ...} Defensive patterns
Strategy: validation
Validate before calling
spec, err := protoutil.UnmarshalChaincodeDeploymentSpec(cdsBytes)
if err != nil { return err }
if spec.ChaincodeSpec.Type != pb.ChaincodeSpec_GOLANG {
return fmt.Errorf("upgrade requires GOLANG spec, got %s", spec.ChaincodeSpec.Type)
} Type guard
func isGolangSpec(spec *pb.ChaincodeSpec) bool { return spec != nil && spec.Type == pb.ChaincodeSpec_GOLANG } Try / catch
inst, err := getUpgradeTxInstance(channelID, cdsBytes)
if err != nil && strings.Contains(err.Error(), "unexpected chaincode type") {
// mark transaction invalid; do not process the upgrade
} Prevention
- Always build system chaincode upgrade specs as GOLANG
- Validate ChaincodeSpec.Type in tooling before submission
- Reject non-Go specs at transaction construction time
- Keep upgrade tooling aligned with legacy LSCC requirements
When it happens
Trigger: getUpgradeTxInstance parses the ChaincodeDeploymentSpec from an upgrade transaction and finds cds.ChaincodeSpec.Type is not GOLANG (e.g., JAVA or NODE).
Common situations: Attempting to upgrade a system chaincode with a spec built for a non-Go type; hand-crafted or corrupted upgrade transaction data in a block; tooling that produced a deployment spec with the wrong CCType field.
Related errors
- only applicable for private data
- did not find a code package inside the package
- illegal file name in payload: %s
- cannot collect files from empty chaincode path
- illegal file detected in payload: "%s"
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/f7925089af4f5bac.
Report an issue: GitHub.