hyperledger/fabric · error

decoded size (%d) from DecodeVarint is more than available b

Error message

decoded size (%d) from DecodeVarint is more than available bytes (%d)

What it means

The encoded value declares a payload size s, but the available bytes after the size byte are fewer than s. This guards against out-of-range slice reads and means the buffer is truncated or the decode offset is wrong.

Source

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

	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. Slice off the correct prefix so the decoder receives exactly size-byte + payload bytes
  2. Verify the composite-key layout matches the writer's version (check key schema/version)
  3. Check ledger data integrity if truncation is unexpected; resync or restore from snapshot
  4. Add a length assertion (len(bytes)-1 >= bytes[0]) before decoding

Example fix

// before
v, _, err := util.DecodeOrderPreservingVarUint64(fullKey) // fullKey has extra prefix
// after
numPart := fullKey[len(prefix):] // pass only the encoded-number portion
v, _, err := util.DecodeOrderPreservingVarUint64(numPart)
Defensive patterns

Strategy: validation

Validate before calling

func hasEnoughBytes(b []byte) bool {
	return len(b) > 0 && int(b[0]) <= len(b)-1
}

Type guard

func isCompleteEncodedUint64(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(), "more than available bytes") {
		log.Errorf("truncated encoded value: need %d payload bytes, got %d", bytes[0], len(bytes)-1)
	}
	return err
}

Prevention

When it happens

Trigger: Calling DecodeOrderPreservingVarUint64 on a truncated slice — e.g. passing the whole composite key where only the numeric suffix should be given, slicing with an off-by-one, or a key corrupted/shortened by an older writer version.

Common situations: Parsing keys returned by an iterator without trimming prefix bytes; upgrading/downgrading between versions with different composite-key layouts; corrupted ledger data after partial writes.

Related errors


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