{"record":{"id":"7f7da56d1ec00748","repo":"neon-bindings/neon","slug":"expected-jsbuffer","errorCode":null,"errorMessage":"expected JsBuffer","messagePattern":"expected JsBuffer","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"crates/neon/src/types_impl/extract/buffer.rs","lineNumber":29,"sourceCode":"    },\n};\n\n/// Wrapper for converting between bytes and [`JsArrayBuffer`](JsArrayBuffer)\npub struct ArrayBuffer<B>(pub B);\n\nimpl<'cx, B> TryFromJs<'cx> for ArrayBuffer<B>\nwhere\n    for<'b> B: From<&'b [u8]>,\n{\n    type Error = TypeExpected<JsBuffer>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        let v = match v.downcast::<JsArrayBuffer, _>(cx) {\n            Ok(v) => v,\n            Err(_) => return Ok(Err(Self::Error::new())),\n        };\n\n        Ok(Ok(ArrayBuffer(B::from(v.as_slice(cx)))))\n    }\n}\n\nimpl<'cx, B> TryIntoJs<'cx> for ArrayBuffer<B>\nwhere\n    B: AsRef<[u8]>,\n{\n    type Value = JsArrayBuffer;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        JsArrayBuffer::from_slice(cx, self.0.as_ref())\n    }\n}\n\nimpl<B> private::Sealed for ArrayBuffer<B> {}","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/neon-bindings/neon/blob/38960e4381d9ad13b551cdf2d261f609167c9bc2/crates/neon/src/types_impl/extract/buffer.rs#L11-L47","documentation":"This is the extraction error produced when `JsValue` cannot be downcast to `JsArrayBuffer` while extracting an `ArrayBuffer` argument in a Neon exported function. The `TryFromJs` impl for `ArrayBuffer<B>` returns `Self::Error` (whose message is \"expected JsBuffer\") when the incoming JS value is not an ArrayBuffer (detached views, plain objects, typed arrays, strings, etc. all fail).","triggerScenarios":"Calling an exported Neon function whose parameter extracts as `ArrayBuffer` with an argument that is not a JS ArrayBuffer: a Buffer, Uint8Array, plain object, null, undefined, or a string.","commonSituations":"Passing a Node Buffer or Uint8Array from JS where the Rust signature expects `ArrayBuffer`; sending `null`/`undefined`; a caller on the JS side changed the value's type after a refactor.","solutions":["Convert the JS value to a real ArrayBuffer before calling: `value.buffer` for typed arrays or `Uint8Array.from(buffer)` for Buffers","Change the Rust signature to accept `JsBuffer`/`Buffer` if callers pass Node Buffers","Accept a broader type in Rust (`&[u8]` via `JsTypedArray`) or handle the error in JS and retry with a converted value"],"exampleFix":"// before (JS)\nconst { readChunk } = require('./native');\nreadChunk(Buffer.from('data'));\n// after (JS)\nconst buf = Buffer.from('data');\nconst ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);\nreadChunk(ab);","handlingStrategy":"type-guard","validationCode":"function isArrayBuffer(x) { return x instanceof ArrayBuffer; }","typeGuard":"function isRealArrayBuffer(v) { return v !== null && v !== undefined && v instanceof ArrayBuffer; }","tryCatchPattern":"try { native.readChunk(arg); } catch (e) { if (String(e).includes('expected JsBuffer')) { native.readChunk(toArrayBuffer(arg)); } else { throw e; } }","preventionTips":["Ensure JS callers pass true ArrayBuffer instances, not Node Buffer or typed arrays","Wrap args: `x instanceof ArrayBuffer ? x : x.buffer` before calling","Keep Rust and JS argument types in sync when refactoring the API","Document the expected binary type on each exported function"],"tags":["rust","neon","arraybuffer","extraction","type-error"],"backgroundTag":"type-mismatch","analyzedSha":"38960e4381d9ad13b551cdf2d261f609167c9bc2","analyzedAt":"2026-09-13T09:05:33.640Z","contentChangedAt":"2026-09-13T09:05:33.640Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}