ruvnet/ruflo · error
HNSW pattern limit reached
Error message
HNSW pattern limit reached (${HNSW_MAX_SAFE_PATTERNS}). What it means
The HNSW router wrapper enforces a hard safety cap of HNSW_MAX_SAFE_PATTERNS = 1024 patterns (exported at ruvllm-wasm.ts:145), independent of the maxPatterns you pass to the constructor. addPattern() throws once the count of successfully added patterns reaches 1024; the cap exists to bound wasm-side memory since HNSW index memory grows with pattern count.
Solutions
- Prune before adding: evict the oldest or lowest-value patterns to stay under 1024
- Shard: partition patterns across multiple HNSW routers (by tenant, topic, or bucket) and merge route() results
- Dedupe by pattern.name before re-adding on restart so counts do not grow monotonically
- Track the count yourself and stop or rotate before hitting the cap (the wrapper exposes no count getter)
Example fix
// before
for (const p of allPatterns) router.addPattern(p); // throws at pattern #1025
// after
import { HNSW_MAX_SAFE_PATTERNS } from './ruvllm-wasm';
let added = 0;
for (const p of allPatterns) {
if (added >= HNSW_MAX_SAFE_PATTERNS) throw new Error('pattern budget exhausted — shard the router');
if (router.addPattern(p)) added++;
} Defensive patterns
Strategy: validation
Validate before calling
import { HNSW_MAX_SAFE_PATTERNS } from './ruvllm-wasm';
function budgetRemaining(added: number): number {
return HNSW_MAX_SAFE_PATTERNS - added; // check before every batch add Type guard
const hasPatternBudget = (added: number): boolean => added < HNSW_MAX_SAFE_PATTERNS;
Try / catch
try {
ok = router.addPattern(p);
} catch (e) {
if (e instanceof Error && e.message.startsWith('HNSW pattern limit reached')) {
evictOldestPattern(); ok = router.addPattern(p); // make room, retry once
} else throw e;
} Prevention
- Track your own add count — the wrapper exposes no getter and the cap (1024) is hard
- Dedupe by pattern.name when replaying history so counts do not grow per restart
- Shard large pattern sets across multiple routers instead of fighting the cap
When it happens
Trigger: Bulk-loading more than 1024 embeddings into one router; accumulating patterns across a long-running process without eviction; replaying an event log into the index on every restart, incrementing past the cap; concurrent producers adding patterns between your count checks.
Common situations: Rebuilding a routing index from history on boot; memory/knowledge ingestion pipelines with no dedupe; multi-tenant designs funneling all tenants' patterns into a single router.
Related errors
- batchProcess requires WASM kernel
- detectDestructive not available in JS fallback; use…
- dimension is required when creating a new memory file
- Failed to initialize @ruvector/ruvllm-wasm
- Failed to initialize @ruvector/rvagent-wasm
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/305f866b4e5e0293.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/ruvector/ruvllm-wasm.ts:173
route: (query: Float32Array, k?: number) => HnswRouteResult[];
clear: () => void;
patternCount: () => number;
toJson: () => string;
}> {
await initRuvllmWasm();
const mod = await import('@ruvector/ruvllm-wasm');
const router = new mod.HnswRouterWasm(config.dimensions, config.maxPatterns);
if (config.efSearch) {
router.setEfSearch(config.efSearch);
}
let count = 0;
return {
addPattern(pattern: HnswPattern): boolean {
if (count >= HNSW_MAX_SAFE_PATTERNS) {
throw new Error(
`HNSW pattern limit reached (${HNSW_MAX_SAFE_PATTERNS}).`
);
}
const metadataJson = JSON.stringify(pattern.metadata ?? {});
// addPattern requires 3 args: (embedding, name, metadata_json)
const ok = router.addPattern(pattern.embedding, pattern.name, metadataJson);
if (ok) count++;
return ok;
},
route(query: Float32Array, k = 3): HnswRouteResult[] {
const raw = router.route(query, k);
return Array.from(raw).map((r: any) => ({
name: r.name ?? r.pattern_name ?? '',
score: r.score ?? r.distance ?? 0,
metadata: r.metadata ? (typeof r.metadata === 'string' ? JSON.parse(r.metadata) : r.metadata) : undefined,
}));
},
clear(): void {View on GitHub (pinned to fa13ee4ad6)