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 agenticow_ingest while iterating records: every record must carry a `vector` that is a non-empty array. Vectors are the embedding payloads indexed by the HNSW store; a missing or empty vector cannot be ingested and would corrupt dimension tracking, so the tool rejects it up front.
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 6b01dc5a68)
Solutions
- Ensure every record has vector: number[] with length > 0 matching the memory dimension.
- Convert typed arrays (Float32Array/Float64Array) via Array.from(...) before passing.
- Filter out malformed records upstream so the ingest batch is uniform.
- If dimension is unset, confirm records[0].vector.length is the intended dimension.
Example fix
// before
{ id: 1, text: 'hello' }
// after
{ id: 1, vector: Array.from(embedding), text: 'hello' } Defensive patterns
Strategy: validation
Validate before calling
function normalizeRecords(records) {
return records.map((r) => {
const vector = Array.isArray(r.vector) ? r.vector : Array.from(r.vector ?? []);
if (vector.length === 0) throw new Error(`record ${r.id ?? '?'} has empty vector`);
return { ...r, vector };
});
} Type guard
function isNonEmptyNumberArray(v: unknown): v is number[] {
return Array.isArray(v) && v.length > 0 && v.every((n) => typeof n === 'number' && Number.isFinite(n));
} Prevention
- Convert typed arrays (Float32Array) via Array.from before passing.
- Treat empty embeddings from the model as a hard error, not a skip.
- Keep record shapes uniform across the batch.
When it happens
Trigger: Any record in the records array whose `vector` is undefined, not an array, or an empty array []. The loop validates each record before opening lineage and before deriving the default dimension from records[0].vector.length.
Common situations: Mixing record shapes where some omit vector; passing text-only payloads; an embedding step that returned [] for a short input; serialising Float32Array which is array-like but fails Array.isArray.
Related errors
- records must be a non-empty array of {id?, vector, text?}
- scoreBy='nearest' requires a probe vector
- candidate ${label} must ingest at least one vector
- vector must be a non-empty numeric array
- Validation failed: ${result.error}
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/69b6d03db9508470.
Report an issue: GitHub.