neon-bindings/neon · error

>= i32::MAX

Error message

{size} >= i32::MAX

What it means

`Utf8::into_small_unwrap` converts a UTF-8 buffer to a `SmallUtf8`, which is only valid when the byte length fits in an `i32` (a Node-API limitation for small strings). If `size() >= i32::MAX` (2 GiB), the conversion returns None and this method panics with the size. It is the panicking sibling of the fallible `into_small`.

Solutions

  1. Use the fallible `into_small()` and handle the None case instead of the `_unwrap` variant.
  2. Check `self.size() < i32::MAX as usize` before calling into_small_unwrap.
  3. Process the data in chunks (streaming read/truncate) rather than holding one >2 GiB string; `truncate()` is provided for this.
  4. Reduce memory pressure: if strings near 2 GiB are expected, switch the pipeline to operate on Buffers/bytes rather than JS strings.

Example fix

// before
let small = utf8.into_small_unwrap(); // panics for >= 2 GiB strings

// after
let small = match utf8.into_small() {
    Some(s) => s,
    None => return cx.throw_error("string exceeds 2 GiB limit"),
};
Defensive patterns

Strategy: validation

Validate before calling

// before converting, check the size bound
if utf8.size() >= i32::MAX as usize {
    return cx.throw_error("string too large for SmallUtf8 (>= 2 GiB)");
}
let small = utf8.into_small_unwrap(); // now safe

Type guard

fn fits_small_utf8(u: &Utf8) -> bool {
    u.size() < i32::MAX as usize
}

Try / catch

// prefer the fallible API and handle the None case explicitly
let small = utf8.into_small();
if small.is_none() { /* chunk or truncate the string instead */ }

Prevention

When it happens

Trigger: Calling `into_small_unwrap()` on a `Utf8` value whose string is 2,147,483,647 bytes or larger — e.g. reading a gigantic file into a JS string and then converting it; concatenating very large strings before conversion.

Common situations: Processing multi-gigabyte text files, logs, or serialized payloads through JS strings; string-building code that accumulates past the 2 GiB boundary before calling into_small_unwrap.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of neon-bindings/neon@38960e4381 (2026-09-13). Data as JSON: /api/errors/f076758cf9d1a9bf. Report an issue: GitHub.

Appendix: source

Thrown at crates/neon/src/types_impl/utf8.rs:50

impl<'a> Utf8<'a> {
    pub fn size(&self) -> usize {
        self.contents.len()
    }

    pub fn into_small(self) -> Option<SmallUtf8<'a>> {
        if self.size() < SMALL_MAX {
            Some(SmallUtf8 {
                contents: self.contents,
            })
        } else {
            None
        }
    }

    pub fn into_small_unwrap(self) -> SmallUtf8<'a> {
        let size = self.size();
        self.into_small().unwrap_or_else(|| {
            panic!("{size} >= i32::MAX");
        })
    }

    pub fn truncate(self) -> SmallUtf8<'a> {
        let size = self.size();
        let mut contents = self.contents;

        if size >= SMALL_MAX {
            let s: &mut String = contents.to_mut();
            s.truncate(SMALL_MAX - 3);
            s.push_str("...");
        }

        SmallUtf8 { contents }
    }
}

View on GitHub (pinned to 38960e4381)