Summary
RvfDatabase.query() in @ruvector/rvf@0.2.3 throws a misleading low-level N-API error when called with an options-object second argument ({k: 2}, {topK: 2}, or {limit: 2}), instead of either accepting the object form or validating the argument type before crossing the N-API boundary.
Environment
@ruvector/rvf@0.2.3 (current npm latest, no 0.2.4+ published as of this report; latest published 2026-07-05)
- Node v26.4.0, macOS arm64, native
@ruvector/rvf-node addon
How to reproduce
import { RvfDatabase } from '@ruvector/rvf';
const db = await RvfDatabase.create('./test.rvf', { dimensions: 8 });
await db.ingestBatch([{ id: 'doc1', vector: new Float32Array(8).fill(0), metadata: {} }]);
await db.query(new Float32Array(8), { k: 2 }); // throws
await db.query(new Float32Array(8), { topK: 2 }); // throws
await db.query(new Float32Array(8), { limit: 2 }); // throws
await db.query(new Float32Array(8), 2); // works
Actual output (all three object forms)
RvfError: Backend initialization failed: Failed to convert napi value Object into
rust type `u32`
(error code 65281)
Reproduced live against the currently installed native addon.
Expected behavior
Either the object form is accepted (most vector-DB JS APIs — including, going by naming conventions used elsewhere in this same package, plausibly this one — accept a {k}-style options object), or the wrapper validates arguments in the TypeScript/JS layer and throws a clear, correctly-scoped error before crossing the N-API boundary. "Backend initialization failed" is actively misleading — it reads as a database-open-time failure, not an argument-type error on a specific call.
Root cause (confirmed by reading source)
dist/database.js declares query(vector, k, options) (line 109). dist/backend.js, NodeBackend.query() (line 149) passes k straight through to this.handle.query(vector, k, nativeOpts) with no type validation in the JS layer — an object passed as k reaches the native N-API boundary unchanged, where napi-rs's raw type-conversion error ("Failed to convert napi value Object into rust type u32") surfaces directly to the caller.
Sample use cases affected
- k-nearest-neighbor query against a local
.rvf vector store, e.g. serving a /api/search?mode=semantic-style endpoint where k is naturally expressed as part of an options object alongside filters
Workaround
Call with k as a bare positional number: db.query(vector, k).
Proposed fix
Accept both call signatures for ergonomics (query(vector, k) and query(vector, { k })), or at minimum validate the k argument's type in dist/database.js/dist/backend.js and throw a typed RvfError (e.g. InvalidArgument) carrying the actual accepted signature in its message, before calling into the native addon. Document the accepted signature explicitly in the README/type defs, which currently don't make it unambiguous.
Summary
RvfDatabase.query()in@ruvector/rvf@0.2.3throws a misleading low-level N-API error when called with an options-object second argument ({k: 2},{topK: 2}, or{limit: 2}), instead of either accepting the object form or validating the argument type before crossing the N-API boundary.Environment
@ruvector/rvf@0.2.3(current npmlatest, no 0.2.4+ published as of this report; latest published 2026-07-05)@ruvector/rvf-nodeaddonHow to reproduce
Actual output (all three object forms)
(error code
65281)Reproduced live against the currently installed native addon.
Expected behavior
Either the object form is accepted (most vector-DB JS APIs — including, going by naming conventions used elsewhere in this same package, plausibly this one — accept a
{k}-style options object), or the wrapper validates arguments in the TypeScript/JS layer and throws a clear, correctly-scoped error before crossing the N-API boundary. "Backend initialization failed" is actively misleading — it reads as a database-open-time failure, not an argument-type error on a specific call.Root cause (confirmed by reading source)
dist/database.jsdeclaresquery(vector, k, options)(line 109).dist/backend.js,NodeBackend.query()(line 149) passeskstraight through tothis.handle.query(vector, k, nativeOpts)with no type validation in the JS layer — an object passed askreaches the native N-API boundary unchanged, where napi-rs's raw type-conversion error ("Failed to convert napi value Object into rust typeu32") surfaces directly to the caller.Sample use cases affected
.rvfvector store, e.g. serving a/api/search?mode=semantic-style endpoint wherekis naturally expressed as part of an options object alongside filtersWorkaround
Call with
kas a bare positional number:db.query(vector, k).Proposed fix
Accept both call signatures for ergonomics (
query(vector, k)andquery(vector, { k })), or at minimum validate thekargument's type indist/database.js/dist/backend.jsand throw a typedRvfError(e.g.InvalidArgument) carrying the actual accepted signature in its message, before calling into the native addon. Document the accepted signature explicitly in the README/type defs, which currently don't make it unambiguous.