ruvnet/ruflo · error · Error
each record requires a non-empty numeric vector
Error message
each record requires a non-empty numeric vector
What it means
Thrown by the agenticow_ingest handler (agenticow-tools.ts:132) when any record's vector field is not a non-empty array. agenticow stores pre-computed numeric vectors (HNSW-indexed) — text is optional metadata, not something that gets embedded on the fly — so every record must carry its own non-empty vector.
Solutions
- Pre-compute embeddings and pass a real number[] per record (e.g. via the claude-flow embeddings tools) — dimension must match the file's dimension
- Parse stringified vectors before sending: JSON.parse(rec.vector)
- Filter or reject records lacking vectors before the call, and align the field name to 'vector'
Example fix
// before
await callTool('agenticow_ingest', {
path: p, dimension: 384,
records: [{ text: 'a doc with no embedding' }], // throws
});
// after
const vectors = await embed(texts); // pre-compute
await callTool('agenticow_ingest', {
path: p, dimension: 384,
records: texts.map((t, i) => ({ vector: vectors[i], text: t })),
}); Defensive patterns
Strategy: validation
Validate before calling
function isNumericVector(v: unknown): v is number[] {
return Array.isArray(v) && v.length > 0 && v.every((n) => typeof n === 'number' && Number.isFinite(n));
}
const bad = records.filter((r) => !isNumericVector(r.vector));
if (bad.length) throw new TypeError(`${bad.length} records lack a numeric vector`); Type guard
function isNumericVector(v: unknown): v is number[] {
return Array.isArray(v) && v.length > 0 && v.every((n) => typeof n === 'number' && Number.isFinite(n));
} Prevention
- This API stores raw vectors — always run your embedding step before ingest, never send text-only records
- Assert every vector's length equals the file's dimension before submitting the batch
- Beware double-stringified JSON turning vectors into strings
When it happens
Trigger: A record with vector omitted (e.g. {text: 'doc'} expecting auto-embedding), vector: [], vector passed as a string ('[0.1,0.2]') or comma-separated '0.1,0.2', or vector: null. One bad record in the batch fails the entire call.
Common situations: Assuming the tool embeds text like a RAG pipeline; vectors JSON.stringify'd twice so they arrive as strings; sparse sources where some rows lack embeddings; undefined after destructuring a renamed field (e.g. record.embedding vs record.vector).
Related errors
- vector must be a non-empty numeric array
- at least one candidate is required
- candidate must ingest at least one vector
- label exceeds 256 chars
- label is required
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/69b6d03db9508470.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/mcp-tools/agenticow-tools.ts:132
required: ['vector'],
},
},
dimension: { type: 'integer', description: 'Vector dimension (required only when path does not exist yet)' },
},
required: ['path', 'records'],
},
handler: async (input) => {
const api = await loadAgenticow();
if (!api) return degradedResult('agenticow-not-found');
const path = resolveMemoryPath(String(input.path));
const records = input.records as Array<{ id?: number; vector: number[]; text?: string }>;
if (!Array.isArray(records) || records.length === 0) {
throw new Error('records must be a non-empty array of {id?, vector, text?}');
}
for (const r of records) {
if (!Array.isArray(r.vector) || r.vector.length === 0) {
throw new Error('each record requires a non-empty numeric vector');
}
}
const dim = (input.dimension as number | undefined) ?? records[0].vector.length;
const mem = await openWithLineage(api, path, dim);
try {
const result = await mem.ingest(records.map((r) => ({
...(typeof r.id === 'number' ? { id: r.id } : {}),
vector: r.vector,
...(r.text !== undefined ? { text: r.text } : {}),
})));
await mem.save?.(manifestFor(path));
return { success: true, path, ingested: result };
} finally {
await mem.close?.();
}
},
},
{View on GitHub (pinned to fa13ee4ad6)