grpc/grpc-go · error

mem: allocating slice of size 2^%d is not possible

Error message

mem: allocating slice of size 2^%d is not possible

What it means

BinaryTieredBufferPool is constructed from power-of-two exponents; at buffer_pool.go:104 each exponent is bounds-checked against maxExponent = uintSize - 2 (62 on 64-bit, 30 on 32-bit platforms). Requesting a tier of size 2^exp where exp exceeds this limit is impossible to allocate as a Go slice on that architecture, so NewBinaryTieredBufferPool/NewDirtyBinaryTieredBufferPool returns an error instead of panicking. The exponent, not the byte count, is printed.

Source

Thrown at internal/mem/buffer_pool.go:105

func newBinaryTiered(sizedPoolFactory func(int) bufferPool, fallbackPool bufferPool, powerOfTwoExponents ...uint8) (*BinaryTieredBufferPool, error) {
	slices.Sort(powerOfTwoExponents)
	powerOfTwoExponents = slices.Compact(powerOfTwoExponents)

	// Determine the maximum exponent we need to support. This depends on the
	// word size (32-bit vs 64-bit).
	maxExponent := uintSize - 2
	indexOfNextLargestBit := slices.Repeat([]int{-1}, maxExponent+1)
	indexOfPreviousLargestBit := slices.Repeat([]int{-1}, maxExponent+1)

	maxTier := 0
	pools := make([]bufferPool, 0, len(powerOfTwoExponents))

	for i, exp := range powerOfTwoExponents {
		// Allocating slices of size > 2^maxExponent isn't possible on
		// maxExponent-bit machines.
		if int(exp) > maxExponent {
			return nil, fmt.Errorf("mem: allocating slice of size 2^%d is not possible", exp)
		}
		tierSize := 1 << exp
		pools = append(pools, sizedPoolFactory(tierSize))
		maxTier = max(maxTier, tierSize)

		// Map the exact power of 2 to this pool index.
		indexOfNextLargestBit[exp] = i
		indexOfPreviousLargestBit[exp] = i
	}

	// Fill gaps for Get() (Next Largest)
	// We iterate backwards. If current is empty, take the value from the right (larger).
	for i := maxExponent - 1; i >= 0; i-- {
		if indexOfNextLargestBit[i] == -1 {
			indexOfNextLargestBit[i] = indexOfNextLargestBit[i+1]
		}
	}

View on GitHub (pinned to 0c51461d27)

Solutions

  1. Confirm you are passing exponents (log2 of the byte size), not raw byte sizes: pass 12 for 4 KiB, 14 for 16 KiB, 20 for 1 MiB.
  2. Clamp/validate the exponent against your platform's maxExponent: keep exponents <= 30 for 32-bit-safe code, <= 62 for 64-bit.
  3. If you genuinely need very large pooled buffers, fall back to a SimpleBufferPool/NopBufferPool that allocates on demand rather than a fixed tier.
  4. Unit-test pool construction with the exact exponents your config permits.

Example fix

// before: passing byte size as exponent
//   pool, err := mem.NewBinaryTieredBufferPool(4096, 16384)
//   // err: allocating slice of size 2^4096 is not possible

// after: pass exponents
//   pool, err := mem.NewBinaryTieredBufferPool(12, 14) // 4 KiB, 16 KiB
Defensive patterns

Strategy: validation

Validate before calling

package main

import (
	"fmt"
	"math/bits"
)

// validExponent returns nil if exp can index a Go slice on this platform.
func validExponent(exp uint8) error {
	maxExp := uint(bits.UintSize) - 2
	if uint(exp) > maxExp {
		return fmt.Errorf("exponent %d exceeds platform max %d", exp, maxExp)
	}
	return nil
}

// func main() {
//     for _, e := range []uint8{12, 14, 20, 40} {
//         if err := validExponent(e); err != nil { fmt.Println(err) }
//     }
// }

Try / catch

// Construction returns the error; check it explicitly.
//
//   pool, err := mem.NewBinaryTieredBufferPool(12, 14, 20)
//   if err != nil {
//       return fmt.Errorf("buffer pool init: %w", err)
//   }

Prevention

When it happens

Trigger: Triggered by NewBinaryTieredBufferPool(powerOfTwoExponents...) or NewDirtyBinaryTieredBufferPool(...) when one of the supplied uint8 exponents is greater than maxExponent (uintSize-2). For example passing 63 on a 64-bit build (2^63 bytes) or any value > 30 on a 32-bit build.

Common situations: A caller mistakenly passes the desired byte size (e.g. 4096, 16384) instead of the exponent (12, 14), or hard-codes an exponent that is valid on 64-bit but breaks 32-bit builds, or derives the exponent from attacker/config-controlled input without clamping.

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/690a628d9508b64b. Report an issue: GitHub.