hyperledger/fabric · error

failed to unmarshal snapshot request

Error message

failed to unmarshal snapshot request

What it means

SnapshotService.Generate first proto-unmarshals the raw bytes of the SignedSnapshotRequest. If the Request bytes are not a valid pb.SnapshotRequest message, the underlying unmarshal error is wrapped with 'failed to unmarshal snapshot request' and returned. The request never reaches the ACL check.

Source

Thrown at core/ledger/snapshotgrpc/snapshot_service.go:44

	LedgerGetter LedgerGetter
	ACLProvider  ACLProvider
}

// LedgerGetter gets the PeerLedger associated with a channel.
type LedgerGetter interface {
	GetLedger(cid string) ledger.PeerLedger
}

// ACLProvider checks ACL for a channelless resource
type ACLProvider interface {
	CheckACLNoChannel(resName string, idinfo any) error
}

// Generate generates a snapshot request.
func (s *SnapshotService) Generate(ctx context.Context, signedRequest *pb.SignedSnapshotRequest) (*emptypb.Empty, error) {
	request := &pb.SnapshotRequest{}
	if err := proto.Unmarshal(signedRequest.Request, request); err != nil {
		return nil, errors.Wrap(err, "failed to unmarshal snapshot request")
	}

	if err := s.checkACL(resources.Snapshot_submitrequest, request.SignatureHeader, signedRequest); err != nil {
		return nil, err
	}

	lgr, err := s.getLedger(request.ChannelId)
	if err != nil {
		return nil, err
	}

	if err := lgr.SubmitSnapshotRequest(request.BlockNumber); err != nil {
		return nil, err
	}

	return &emptypb.Empty{}, nil
}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Regenerate the request using protoutil/SnapshotRequest marhsaling helpers so .Request holds valid protobuf bytes.
  2. Confirm the client and peer use matching .proto definitions for SnapshotRequest (same protobuf version).
  3. Check any transport encoding (base64/compression) is not truncating the payload.
  4. Log proto.Unmarshal's wrapped cause — it names the exact byte-offset failure for diagnosis.

Example fix

// before
req := &pb.SnapshotRequest{SignatureHeader: hdr}
signed := &pb.SignedSnapshotRequest{Request: []byte(fmt.Sprintf("%v", req))}
// after
raw, _ := proto.Marshal(req)
signed := &pb.SignedSnapshotRequest{Request: raw, Signature: sig}
Defensive patterns

Strategy: validation

Validate before calling

var probe pb.SnapshotRequest
if err := proto.Unmarshal(signedReq.Request, &probe); err != nil {
    return fmt.Errorf("client-side check: request payload is not a valid SnapshotRequest: %w", err)
}
resp, err := svc.Generate(ctx, signedReq)

Type guard

func isValidSnapshotRequest(raw []byte) bool {
    var r pb.SnapshotRequest
    return proto.Unmarshal(raw, &r) == nil
}

Try / catch

resp, err := svc.Generate(ctx, signedReq)
if err != nil {
    if strings.Contains(err.Error(), "failed to unmarshal snapshot request") {
        // re-marshal payload with proto.Marshal and retry once
    }
    return err
}

Prevention

When it happens

Trigger: Sending Generate a signed request whose .Request field is nil, empty, truncated, or serialized with the wrong message type (e.g. a SnapshotQuery instead of SnapshotRequest, or a JSON body instead of protobuf).

Common situations: Client SDKs building the request manually with wrong field encoding; middleware/base64 corruption when relaying the signed request; version mismatch where client and peer protobuf definitions differ; tests posting empty payloads.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


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