graph-node 2.1.0: createEdge/batchInsert silently discard metadata, blocking lossless recovery
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 4.5k
- Forks
- 603
- Avg merge
- 23h 32m
- Merged PRs (30d)
- 59
Description
Reproduced on the current published native binding
@ruvector/graph-node@2.1.0 (npm latest checked 2026-09-13), Node 24.14.1, macOS arm64. Resolved from @claude-flow/cli@3.41.2.
Both createEdge() and batchInsert() accept the documented metadata: Record<string,string>, return successful edge IDs, and retain endpoints/connectivity after a fresh-process reopen. However, all supplied edge metadata is absent from query results before and after reopen. Node properties round-trip in the same fixture.
Source inspection confirms this is not merely a result projection: create_edge and batch_insert build persisted edge properties from only __confidence and __embedding, never copying edge.metadata. run_query returns non-internal properties, so public metadata would be observable if stored.
Minimal disposable reproduction
Use a new temporary directory, never a live managed graph. Run writer and reader in separate processes against that temporary path.
const db = new GraphDatabase({
storagePath: temporaryGraphPath, dimensions: 8, distanceMetric: 'Cosine'
});
const embedding = new Float32Array([1,0,0,0,0,0,0,0]);
for (const id of ['mem:a', 'mem:b', 'mem:c'])
await db.createNode({ id, embedding, properties: { diagnostic: 'true' } });
const edge = {
from: 'mem:a', to: 'mem:b', description: 'supports', embedding,
confidence: 0.75,
metadata: {
sourceEdgeId: 'fixture-source-edge',
weight: '0.8',
metadata: JSON.stringify({ witness: 'fixture-witness' })
}
};
await db.createEdge(edge);
await db.batchInsert({ nodes: [], edges: [{ ...edge, to: 'mem:c' }] });
console.log(await db.query('MATCH (a)-[r]->(b) RETURN a,r,b'));
// nodes: diagnostic property retained
// both edges: properties: {}
A fresh reader process with the same options returns the same endpoints/types and empty edge properties. Counts remain 3 nodes / 2 edges. This issue does not dispute the connectivity/persistence fixes in #809/#879/#938.
Impact and bounded proposed fix
This blocks lossless reconstruction of a native graph from retained managed SQL relationships: weights carried as public metadata, witnesses, original SQL edge identity and other metadata cannot be verified or retained by this API. Retrying causal-edge writes in Ruflo is not an acceptable workaround because that handler also writes SQL.
- Copy public
JsEdge.metadatainto stored edge properties in both single and batch insertion, with an explicit collision policy for reserved internal keys. - Preserve native confidence/embedding handling; do not repurpose relation type or node IDs to smuggle metadata.
- Test exact public metadata before and after a separate-process reopen, including Unicode, JSON strings and reserved-key behavior.
- Audit
createHyperedge()separately: source appears to ignore its metadata too, but the executed reproduction above covers ordinary edges only. - Keep missing metadata observable; do not return successful import/recovery receipts without fidelity verification.
Related downstream persistence adapter fix: https://github.com/ruvnet/ruflo/issues/3313 . The constructor patch enables durable future graph writes but cannot repair this compiled native metadata omission. No production databases were changed during these tests.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in crates/ruvector-graph-node/src/lib.rs at the create_edge and batch_insert implementation, then run the disposable two-process JavaScript reproduction against a temporary graph path. Done means public edge metadata, including Unicode and JSON strings, is returned before and after reopen, while confidence and embedding handling and reserved-key behavior remain correct.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, rust
- Domain
- api, databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100