hyperledger/fabric · error

number of consumed bytes from DecodeVarint is invalid, expec

Error message

number of consumed bytes from DecodeVarint is invalid, expected 1, but got %d

What it means

DecodeOrderPreservingVarUint64 expects its input to be an order-preserving encoded uint64: exactly one size byte followed by the payload. proto.DecodeVarint must consume exactly 1 byte for that size prefix; if it consumes 0 or more than 1, the input is not valid order-preserving encoding and this error is returned.

Source

Thrown at common/ledger/util/util.go:64

		panic(fmt.Errorf("[]sizeBytes should not be more than one byte because the max number it needs to hold is 8. size=%d", size))
	}
	encodedBytes := make([]byte, size+1)
	encodedBytes[0] = sizeBytes[0]
	copy(encodedBytes[1:], bytes[startingIndex:])
	return encodedBytes
}

// DecodeOrderPreservingVarUint64 decodes the number from the bytes obtained from method 'EncodeOrderPreservingVarUint64'.
// It returns the decoded number, the number of bytes that are consumed in the process, and an error if the input bytes are invalid.
func DecodeOrderPreservingVarUint64(bytes []byte) (uint64, int, error) {
	s, numBytes := protowire.ConsumeVarint(bytes)
	if numBytes < 0 {
		s, numBytes = 0, 0
	}

	switch {
	case numBytes != 1:
		return 0, 0, errors.Errorf("number of consumed bytes from DecodeVarint is invalid, expected 1, but got %d", numBytes)
	case s > 8:
		return 0, 0, errors.Errorf("decoded size from DecodeVarint is invalid, expected <=8, but got %d", s)
	case int(s) > len(bytes)-1:
		return 0, 0, errors.Errorf("decoded size (%d) from DecodeVarint is more than available bytes (%d)", s, len(bytes)-1)
	default:
		// no error
		size := int(s)
		decodedBytes := make([]byte, 8)
		copy(decodedBytes[8-size:], bytes[1:size+1])
		numBytesConsumed := size + 1
		return binary.BigEndian.Uint64(decodedBytes), numBytesConsumed, nil
	}
}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Verify the bytes were created with EncodeOrderPreservingVarUint64 and that you are decoding from the correct offset in the composite key
  2. Check key-encoding version compatibility between writer and reader of the ledger data
  3. Validate input length >= 1 and first byte < 0x80 before decoding
  4. Dump the raw key bytes (hex) and confirm the layout matches the expected composite-key scheme

Example fix

// before
blockNum, _, err := util.DecodeOrderPreservingVarUint64(rawKey) // rawKey includes namespace prefix
// after
if len(rawKey) == 0 || rawKey[0] >= 0x80 {
	return fmt.Errorf("not an order-preserving encoded uint64")
}
blockNum, _, err := util.DecodeOrderPreservingVarUint64(rawKey)
Defensive patterns

Strategy: validation

Validate before calling

func canDecode(buf []byte) bool {
	if len(buf) == 0 { return false }
	return buf[0] < 0x80 // DecodeVarint must consume exactly 1 size byte
}

Type guard

func isOrderPreservingEncoded(b []byte) bool {
	return len(b) > 0 && b[0] >= 1 && b[0] <= 8 && len(b) >= int(b[0])+1
}

Try / catch

v, n, err := util.DecodeOrderPreservingVarUint64(bytes)
if err != nil {
	if strings.Contains(err.Error(), "number of consumed bytes") {
		log.Errorf("input is not order-preserving encoded: % x", bytes)
	}
	return err
}

Prevention

When it happens

Trigger: Calling DecodeOrderPreservingVarUint64 (via retrieveTxID, retrieveBlockNum, NewHeightFromBytes) on bytes that were not produced by EncodeOrderPreservingVarUint64 — e.g. empty input, a first byte >= 0x80 (multi-byte varint), or raw big-endian/protobuf-encoded integers.

Common situations: Reading composite keys written by a different encoder version; decoding a key with the wrong offset (skipping or including extra prefix bytes); hand-crafted keys in tests (TestDecodingBadInputBytes); interpreting another field as the numeric portion of a key.

Related errors


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