hyperledger/fabric · error

proto: Marshal called with nil

Error message

proto: Marshal called with nil

What it means

SignSecret returns this error when the given *gossip.Secret is nil, mirroring the message protobuf's Marshal would emit. It short-circuits before proto.Marshal to avoid a panic/nil error deeper in serialization.

Source

Thrown at gossip/protoext/signing.go:28

	"errors"
	"fmt"

	"github.com/hyperledger/fabric-protos-go-apiv2/gossip"
	"google.golang.org/protobuf/proto"
)

// Signer signs a message, and returns (signature, nil)
// on success, and nil and an error on failure.
type Signer func(msg []byte) ([]byte, error)

// Verifier receives a peer identity, a signature and a message and returns nil
// if the signature on the message could be verified using the given identity.
type Verifier func(peerIdentity []byte, signature, message []byte) error

// SignSecret signs the secret payload and creates a secret envelope out of it.
func SignSecret(e *gossip.Envelope, signer Signer, secret *gossip.Secret) error {
	if secret == nil {
		return errors.New("proto: Marshal called with nil")
	}
	payload, err := proto.Marshal(secret)
	if err != nil {
		return err
	}
	sig, err := signer(payload)
	if err != nil {
		return err
	}
	e.SecretEnvelope = &gossip.SecretEnvelope{
		Payload:   payload,
		Signature: sig,
	}
	return nil
}

// NoopSign creates a SignedGossipMessage with a nil signature
func NoopSign(m *gossip.GossipMessage) (*SignedGossipMessage, error) {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Pass a non-nil gossip.Secret to SignSecret, or skip signing entirely when no secret exists
  2. Check the upstream code path that produced the Secret and fix the nil assignment
  3. Guard the call site: only call SignSecret when a secret is required and present

Example fix

// before
protoext.SignSecret(envelope, signer, secret) // secret may be nil
// after
if secret != nil {
    err := protoext.SignSecret(envelope, signer, secret)
}
Defensive patterns

Strategy: type-guard

Validate before calling

if secret == nil {
    return nil // nothing to sign; skip SignSecret
}

Type guard

func hasSecret(s *gossip.Secret) bool { return s != nil }

Try / catch

if err := protoext.SignSecret(env, signer, secret); err != nil {
    if err.Error() == "proto: Marshal called with nil" {
        return fmt.Errorf("no secret provided to sign: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling SignSecret(e, signer, nil) — e.g. an envelope that has no SecretEnvelope content to attach, or a caller passing a nil secret extracted from a failed parse.

Common situations: Building authenticated gossip envelopes where the secret (e.g. internal endpoint) is absent; refactoring code that changed when secrets are populated; tests passing nil for brevity.

Related errors


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