hyperledger/fabric · error

unexpected error while marshaling TxIDIndexValProto message

Error message

unexpected error while marshaling TxIDIndexValProto message

What it means

Thrown in blockindex.indexBlock when proto.Marshal fails on a TxIDIndexValProto message built for the transaction-ID index. Protobuf marshal of a generated, validly-populated message practically never fails, so this is treated as 'unexpected' and indicates an internal invariant break (nil message, invalid proto definition/registry mismatch).

Solutions

  1. Read the wrapped cause beneath this message for the actual marshal error and identify which message fails.
  2. Rebuild with the pinned protobuf/gogo-protobuf versions from go.mod (go mod tidy / go mod download; clear module cache if suspect).
  3. Regenerate the proto types (protoc-gen-gogo) with the same generator versions the project uses instead of hand-editing generated code.
  4. If it reproduces on one specific block, capture the block and file an issue; the block may contain data that trips the indexer (e.g. nil tx payload paths).

Example fix

// before: mismatched generated code after upgrading protobuf runtime
// ERROR: unexpected error while marshaling TxIDIndexValProto message
// after:
go mod tidy
go build ./...  // ensure pb.go regenerated with project's protoc-gen-gogo version
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: smoke-test marshal of the index value type before processing production blocks
func marshalOK(v *proto.TxIDIndexValProto) error {
	if v == nil {
		return errors.New("nil index value")
	}
	_, err := proto.Marshal(v)
	return err
}

Try / catch

// Go: log the wrapped cause with block/tx identifiers before failing the batch
if err := indexBlock(block); err != nil {
	if strings.Contains(err.Error(), "marshaling TxIDIndexValProto") {
		logger.Errorf("index marshal failed for block %d: %+v", block.Header.Number, errors.Cause(err))
	}
	return err
}

Prevention

When it happens

Trigger: indexBlock (invoked from addBlock or syncIndex) while indexing transactions: only if the TxIDIndexValProto instance is nil or the proto message/registry is inconsistent (mismatched generated code vs runtime protobuf library, malformed proto descriptors).

Common situations: Custom builds where protoc-generated pb.go files were regenerated with an incompatible protoc/protobuf-go version; binary patches to the ledger package; corrupted Go module cache producing stale generated code.

Related errors


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

Appendix: source

Thrown at common/ledger/blkstorage/blockindex.go:122

	if index.isAttributeIndexed(IndexableAttrBlockNum) {
		batch.Put(constructBlockNumKey(blkNum), flpBytes)
	}

	// Index3 Used to find a transaction by its transaction id
	if index.isAttributeIndexed(IndexableAttrTxID) {
		for i, txoffset := range txOffsets {
			txFlp := newFileLocationPointer(flp.fileSuffixNum, flp.offset, txoffset.loc)
			logger.Debugf("Adding txLoc [%s] for tx ID: [%s] to txid-index", txFlp, txoffset.txID)
			txFlpBytes := txFlp.marshal()

			indexVal := &TxIDIndexValue{
				BlkLocation:      flpBytes,
				TxLocation:       txFlpBytes,
				TxValidationCode: int32(txsfltr.Flag(i)),
			}
			indexValBytes, err := proto.Marshal(indexVal)
			if err != nil {
				return errors.Wrap(err, "unexpected error while marshaling TxIDIndexValProto message")
			}
			batch.Put(
				constructTxIDKey(txoffset.txID, blkNum, uint64(i)),
				indexValBytes,
			)
		}
	}

	// Index4 - Store BlockNumTranNum will be used to query history data
	if index.isAttributeIndexed(IndexableAttrBlockNumTranNum) {
		for i, txoffset := range txOffsets {
			txFlp := newFileLocationPointer(flp.fileSuffixNum, flp.offset, txoffset.loc)
			logger.Debugf("Adding txLoc [%s] for tx number:[%d] ID: [%s] to blockNumTranNum index", txFlp, i, txoffset.txID)
			txFlpBytes := txFlp.marshal()
			batch.Put(constructBlockNumTranNumKey(blkNum, uint64(i)), txFlpBytes)
		}
	}

View on GitHub (pinned to 2736b63f8f)