neon-bindings/neon · error · TypeError

expected JsTypedArray

Error message

expected JsTypedArray<T>

What it means

This error is returned by the `TryFromJs` impl for `Vec<u8>` (and typed-array-backed slices): the JS value must downcast to `JsTypedArray<T>`. The message "expected JsTypedArray<T>" fires when the value is not a JS typed array view — ArrayBuffers, Buffers (which are Uint8Array but not detected as a generic typed array here), objects, null, or undefined fail the downcast.

Solutions

  1. Pass a typed array view: `new Uint8Array(arrayBuffer)` instead of the ArrayBuffer itself
  2. Use `Buffer.from(x)` / `new Uint8Array(x)` in JS to build a typed array before calling
  3. Loosen the Rust parameter to a type accepting all binary shapes, or validate and convert in JS first

Example fix

// before (JS)
native.sumBytes(await file.arrayBuffer());
// after (JS)
native.sumBytes(new Uint8Array(await file.arrayBuffer()));
Defensive patterns

Strategy: type-guard

Validate before calling

function isTypedArray(x) { return ArrayBuffer.isView(x) && !(x instanceof DataView); }

Type guard

function isTypedArray(v) { return v !== null && v !== undefined && ArrayBuffer.isView(v) && !(v instanceof DataView); }

Try / catch

try { native.sumBytes(arg); } catch (e) { if (String(e).includes('expected JsTypedArray')) { native.sumBytes(new Uint8Array(arg instanceof ArrayBuffer ? arg : arg.buffer)); } else { throw e; } }

Prevention

When it happens

Trigger: Calling an exported Neon function whose parameter extracts as a typed-array-backed `Vec`/slice with a non-typed-array argument: raw ArrayBuffer, DataView, plain object, null, undefined.

Common situations: Passing `ArrayBuffer` directly instead of a view over it; passing a Node Buffer created via a path the downcast rejects; passing null for a supposed-optional binary argument.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at crates/neon/src/types_impl/extract/buffer.rs:109

    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {
        JsTypedArray::from_slice(cx, self.as_slice())
    }
}

impl<'cx, T> TryFromJs<'cx> for Vec<T>
where
    JsTypedArray<T>: Value,
    T: Binary,
{
    type Error = TypeExpected<JsTypedArray<T>>;

    fn try_from_js(
        cx: &mut Cx<'cx>,
        v: Handle<'cx, JsValue>,
    ) -> NeonResult<Result<Self, Self::Error>> {
        let v = match v.downcast::<JsTypedArray<T>, _>(cx) {
            Ok(v) => v,
            Err(_) => return Ok(Err(Self::Error::new())),
        };

        Ok(Ok(v.as_slice(cx).to_vec()))
    }
}

impl<T> private::Sealed for Vec<T>
where
    JsTypedArray<T>: Value,
    T: Binary,
{
}

impl<'cx, T, const N: usize> TryIntoJs<'cx> for [T; N]
where
    JsTypedArray<T>: Value,
    T: Binary,
{

View on GitHub (pinned to 38960e4381)