ipfs/kubo · error

HAMT fanout must be a power of 2, between 8 and 1024 (got %d

Error message

HAMT fanout must be a power of 2, between 8 and 1024 (got %d)

What it means

When sharding a directory as a HAMT, the fanout is the width of each shard's bitfield. The UnixFS spec constrains it to a power of 2 between 8 and 1024 so the bitfield stays byte-aligned; MaxHAMTFanout rejects any other value up front.

Source

Thrown at core/coreiface/options/unixfs.go:241

}

// MaxDirectoryLinks specifies the maximum number of children for UnixFS basic
// directory nodes.
func (unixfsOpts) MaxDirectoryLinks(n int) UnixfsAddOption {
	return func(settings *UnixfsAddSettings) error {
		settings.MaxDirectoryLinks = n
		settings.MaxDirectoryLinksSet = true
		return nil
	}
}

// MaxHAMTFanout specifies the maximum width of the HAMT directory shards.
// Per the UnixFS spec, the value must be a power of 2, minimum 8
// (for byte-aligned bitfields), and maximum 1024.
func (unixfsOpts) MaxHAMTFanout(n int) UnixfsAddOption {
	return func(settings *UnixfsAddSettings) error {
		if n < 8 || n&(n-1) != 0 || n > 1024 {
			return fmt.Errorf("HAMT fanout must be a power of 2, between 8 and 1024 (got %d)", n)
		}
		settings.MaxHAMTFanout = n
		settings.MaxHAMTFanoutSet = true
		return nil
	}
}

// SizeEstimationMode specifies how directory size is estimated for HAMT sharding decisions.
func (unixfsOpts) SizeEstimationMode(mode io.SizeEstimationMode) UnixfsAddOption {
	return func(settings *UnixfsAddSettings) error {
		settings.SizeEstimationMode = &mode
		settings.SizeEstimationModeSet = true
		return nil
	}
}

// Inline tells the adder to inline small blocks into CIDs
func (unixfsOpts) Inline(enable bool) UnixfsAddOption {

View on GitHub (pinned to 329838acdf)

Solutions

  1. Pick the nearest valid power of two within [8,1024]: 8, 16, 32, 64, 128, 256, 512, or 1024
  2. If the desired value exceeds 1024 (e.g. js-ipfs 2048), clamp to 1024 — it is the maximum the UnixFS spec allows
  3. If you did not set fanout intentionally, drop the MaxHAMTFanout option and let the default apply

Example fix

// before
opt := options.Unixfs.MaxHAMTFanout(2048) // error: between 8 and 1024

// after
opt := options.Unixfs.MaxHAMTFanout(1024)
Defensive patterns

Strategy: validation

Validate before calling

func clampHAMTFanout(n int) int {
    if n < 8 {
        return 8
    }
    if n > 1024 {
        return 1024
    }
    // snap up to next power of two
    p := 8
    for p < n {
        p *= 2
    }
    return p
}
n := clampHAMTFanout(desired)
opt := options.Unixfs.MaxHAMTFanout(n)

Type guard

func isPowerOfTwoInRange8to1024(n int) bool {
    return n >= 8 && n <= 1024 && n&(n-1) == 0
}

Try / catch

opts, err := options.Unixfs.Add(options.Unixfs.MaxHAMTFanout(n))
if err != nil {
    if strings.Contains(err.Error(), "HAMT fanout") {
        // retry with spec-legal default
        opts, err = options.Unixfs.Add(options.Unixfs.MaxHAMTFanout(256))
    }
    if err != nil {
        return err
    }
}

Prevention

When it happens

Trigger: Calling options.Unixfs.MaxHAMTFanout(n) with n < 8 (e.g. 4), n > 1024 (e.g. 2048), or n not a power of two (e.g. 100, 300), then passing the option to UnixfsAddOptions/Add.

Common situations: Reading 'fanout' defaults from other tools (js-ipfs HAMT uses 2048 in some configs, which kubo rejects); computing fanout as bucket count from data size; typos like 1250; users porting configs where a non-power-of-2 was tolerated.

Related errors


AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03). Data as JSON: /api/errors/f4b8dde1a0a55552. Report an issue: GitHub.