spacejam/sled · error

Db's LEAF_FANOUT const generic must be 3 or greater.

Error message

Db's LEAF_FANOUT const generic must be 3 or greater.

What it means

This library is generic over a const LEAF_FANOUT for its B-tree leaf nodes, and Db::open rejects any value below 3 because a leaf needs at least a valid minimum branching capacity. It is thrown eagerly at open time so an invalid database layout is never created or persisted.

Solutions

  1. Change the const generic argument to a value of 3 or greater at the Db::open call site
  2. If the value comes from a named constant, raise that constant's definition to >= 3
  3. Assert the fanout at compile time with a const assertion so the failure happens before open

Example fix

// before
let db = config.open::<2>()?;
// after
let db = config.open::<4>()?;
Defensive patterns

Strategy: validation

Validate before calling

const LEAF_FANOUT: usize = 4;
const _: () = assert!(LEAF_FANOUT >= 3, "LEAF_FANOUT must be >= 3");
let db = config.open::<LEAF_FANOUT>()?;

Try / catch

match config.open::<FANOUT>() {
    Ok(db) => db,
    Err(e) if e.to_string().contains("LEAF_FANOUT") => panic!("config bug: fanout too small"),
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling Config::open::<LEAF_FANOUT>() with LEAF_FANOUT set to 0, 1, or 2 (e.g. open::<2>()) instead of an integer >= 3.

Common situations: Copy-pasting a small const generic during experimentation, computing the fanout from another constant that defaults to a tiny value, or typos like open::<0>() intended as a placeholder.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of spacejam/sled@e449d17111 (2026-09-12). Data as JSON: /api/errors/0067830e8290ab36. Report an issue: GitHub.

Appendix: source

Thrown at src/config.rs:148

    pub fn path<P: AsRef<Path>>(mut self, path: P) -> Config {
        self.path = path.as_ref().to_path_buf();
        self
    }

    builder!(
        (flush_every_ms, Option<usize>, "Start a background thread that flushes data to disk every few milliseconds. Defaults to every 200ms."),
        (cache_capacity_bytes, usize, "Cache size in **bytes**. Default is 512mb."),
        (entry_cache_percent, u8, "The percentage of the cache that is dedicated to the scan-resistant entry cache."),
        (zstd_compression_level, i32, "The zstd compression level to use when writing data to disk. Defaults to 3."),
        (target_heap_file_fill_ratio, f32, "A float between 0.0 and 1.0 that controls how much fragmentation can exist in a file before GC attempts to recompact it."),
        (max_inline_value_threshold, usize, "Values larger than this configurable will be stored as separate blob")
    );

    pub fn open<const LEAF_FANOUT: usize>(
        &self,
    ) -> io::Result<Db<LEAF_FANOUT>> {
        if LEAF_FANOUT < 3 {
            return Err(annotate!(io::Error::new(
                io::ErrorKind::Unsupported,
                "Db's LEAF_FANOUT const generic must be 3 or greater."
            )));
        }
        Db::open_with_config(self)
    }
}

View on GitHub (pinned to e449d17111)