hyperledger/fabric · error
signer is required when creating a signed transaction
Error message
signer is required when creating a signed transaction
What it means
CreateSignedTx requires a Signer to sign the assembled transaction; if the signer parameter is nil it returns this error. Even with valid proposal and responses, no signature can be produced without a signing identity.
Source
Thrown at protoutil/txutils.go:148
Sign(msg []byte) ([]byte, error)
Serialize() ([]byte, error)
}
// CreateSignedTx assembles an Envelope message from proposal, endorsements,
// and a signer. This function should be called by a client when it has
// collected enough endorsements for a proposal to create a transaction and
// submit it to peers for ordering
func CreateSignedTx(
proposal *peer.Proposal,
signer Signer,
resps ...*peer.ProposalResponse,
) (*common.Envelope, error) {
if len(resps) == 0 {
return nil, errors.New("at least one proposal response is required")
}
if signer == nil {
return nil, errors.New("signer is required when creating a signed transaction")
}
// the original header
hdr, err := UnmarshalHeader(proposal.Header)
if err != nil {
return nil, err
}
// the original payload
pPayl, err := UnmarshalChaincodeProposalPayload(proposal.Payload)
if err != nil {
return nil, err
}
// check that the signer is the same that is referenced in the header
signerBytes, err := signer.Serialize()
if err != nil {
return nil, errView on GitHub (pinned to 2736b63f8f)
Solutions
- Pass a valid signing identity (e.g. from msp.NewSigningIdentity or the local MSP) to CreateSignedTx
- Check that the local MSP and signing identity are loaded before transaction assembly
- Verify keystore/certificate paths and that identity retrieval returned non-nil (check err, not just value)
- If the code path allows unsigned operation, use the appropriate constructor instead of CreateSignedTx
Example fix
// before
env, err := protoutil.CreateSignedTx(proposal, nil, resps...)
// after
signer, err := localMSP.GetDefaultSigningIdentity()
if err != nil {
return nil, err
}
env, err := protoutil.CreateSignedTx(proposal, signer, resps...) Defensive patterns
Strategy: type-guard
Validate before calling
func requireSigner(signer protoutil.Signer) error {
if signer == nil {
return fmt.Errorf("signing identity not loaded")
}
return nil
} Type guard
func hasSigner(s protoutil.Signer) bool {
if s == nil { return false }
v := reflect.ValueOf(s)
return !(v.Kind() == reflect.Ptr && v.IsNil())
} Try / catch
signer, err := localMSP.GetDefaultSigningIdentity()
if err != nil || signer == nil {
return nil, fmt.Errorf("no signing identity: %w", err)
}
tx, err := protoutil.CreateSignedTx(proposal, signer, resps...) Prevention
- Load and verify the signing identity at client startup, not at tx assembly time
- Check both err and nil on identity lookups (typed-nil interface pitfall)
- Verify keystore/cert paths in MSP configuration
When it happens
Trigger: Calling CreateSignedTx(proposal, nil, resps...) or passing a nil-valued interface (e.g. a nil *msp.SigningIdentity stored in an interface) returned by an unchecked identity lookup.
Common situations: Client not properly initialized with an MSP/signing identity; identity loaded after a config/env var miss; a SigningIdentity variable left nil because credential files were missing.
Related errors
- failed signing Request
- signer must be the same as the one referenced in the header
- failed unmarshaling identity %s
- could not create a signed Deliver SeekInfo message, somethin
- must provide an instantiation policy
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/38badab7efb7b256.
Report an issue: GitHub.