hyperledger/fabric · error · VSCCEndorsementPolicyError
malformed chaincode invocation spec
Error message
malformed chaincode invocation spec
What it means
When a transaction calls lscc, VSCC's ValidateLSCCInvocation re-validates the original proposal payload. This error means the ChaincodeInvocationSpec unmarshaled from the payload has no ChaincodeSpec, no Input, or nil Args — the invocation structure is incomplete, so it cannot be validated. The transaction is rejected as a policy error.
Source
Thrown at core/handlers/validation/builtin/v12/validation_logic.go:506
) commonerrors.TxValidationError {
cpp, err := protoutil.UnmarshalChaincodeProposalPayload(cap.ChaincodeProposalPayload)
if err != nil {
logger.Errorf("VSCC error: GetChaincodeProposalPayload failed, err %s", err)
return policyErr(err)
}
cis := &pb.ChaincodeInvocationSpec{}
err = proto.Unmarshal(cpp.Input, cis)
if err != nil {
logger.Errorf("VSCC error: Unmarshal ChaincodeInvocationSpec failed, err %s", err)
return policyErr(err)
}
if cis.ChaincodeSpec == nil ||
cis.ChaincodeSpec.Input == nil ||
cis.ChaincodeSpec.Input.Args == nil {
logger.Errorf("VSCC error: committing invalid vscc invocation")
return policyErr(fmt.Errorf("malformed chaincode invocation spec"))
}
lsccFunc := string(cis.ChaincodeSpec.Input.Args[0])
lsccArgs := cis.ChaincodeSpec.Input.Args[1:]
logger.Debugf("VSCC info: ValidateLSCCInvocation acting on %s %#v", lsccFunc, lsccArgs)
switch lsccFunc {
case lscc.UPGRADE, lscc.DEPLOY:
logger.Debugf("VSCC info: validating invocation of lscc function %s on arguments %#v", lsccFunc, lsccArgs)
if len(lsccArgs) < 2 {
return policyErr(fmt.Errorf("Wrong number of arguments for invocation lscc(%s): expected at least 2, received %d", lsccFunc, len(lsccArgs)))
}
if (!ac.PrivateChannelData() && len(lsccArgs) > 5) ||
(ac.PrivateChannelData() && len(lsccArgs) > 6) {
return policyErr(fmt.Errorf("Wrong number of arguments for invocation lscc(%s): received %d", lsccFunc, len(lsccArgs)))View on GitHub (pinned to 2736b63f8f)
Solutions
- Fix the client to construct a complete ChaincodeInvocationSpec with ChaincodeSpec, Input, and at least one Arg (the lscc function name).
- Use the SDK's high-level invoke/chaincode-install APIs instead of manually assembling protobuf envelopes.
- Verify the marshaled proposal payload is not truncated or altered between endorsement and commit.
- Re-submit the transaction; the rejected tx cannot be repaired post-commit.
Example fix
// before: incomplete spec
cis := &pb.ChaincodeInvocationSpec{}
// after: fully populated
cis := &pb.ChaincodeInvocationSpec{
ChaincodeSpec: &pb.ChaincodeSpec{
Type: pb.ChaincodeSpec_GOLANG,
ChaincodeId: &pb.ChaincodeID{Name: "lscc"},
Input: &pb.ChaincodeInput{Args: [][]byte{[]byte("deploy"), ccName, ccVersion, cdsBytes}},
},
} Defensive patterns
Strategy: validation
Validate before calling
// client-side check before submitting an lscc invocation
if cis.ChaincodeSpec == nil || cis.ChaincodeSpec.Input == nil || len(cis.ChaincodeSpec.Input.Args) == 0 {
return errors.New("refusing to submit: ChaincodeInvocationSpec is missing ChaincodeSpec/Input/Args")
} Type guard
func isWellFormedInvocationSpec(cis *pb.ChaincodeInvocationSpec) bool {
return cis != nil && cis.ChaincodeSpec != nil &&
cis.ChaincodeSpec.Input != nil &&
cis.ChaincodeSpec.Input.Args != nil && len(cis.ChaincodeSpec.Input.Args) > 0
} Prevention
- Use SDK/CLI APIs to build proposals rather than hand-assembling envelopes.
- Validate the populated spec struct before marshaling and submitting.
- Never mutate envelope bytes between endorsement and commit.
When it happens
Trigger: Committing a transaction whose ChaincodeProposalPayload.Input does not unmarshal into a fully-populated ChaincodeInvocationSpec: ChaincodeSpec == nil, ChaincodeSpec.Input == nil, or ChaincodeSpec.Input.Args == nil — e.g. a hand-crafted or truncated proposal envelope.
Common situations: Custom client code building envelopes manually with missing fields; SDK misuse where the invoke spec was never populated; tampered or corrupted transactions; testing tools that submit partially-filled ChaincodeInvocationSpec messages.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed unmarshalling lscc read value into ChaincodeData
- unmarshalling ChaincodeQueryResponse failed
- invalid collection configuration supplied for chaincode %s:%
- Wrong number of arguments for invocation lscc(%s): expected
- Wrong number of arguments for invocation lscc(%s): received
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/f88592ea17d58b81.
Report an issue: GitHub.