ruvnet/ruflo · error · Error
records must be a non-empty array of {id?, vector, text?}
Error message
records must be a non-empty array of {id?, vector, text?} What it means
Thrown by the agenticow_ingest MCP tool handler when the `records` argument is not a non-empty array. Ingest is the write half that populates a branch or base with vectors, so at least one record shaped {id?, vector, text?} must be present. The guard runs before any lineage file is opened.
Source
Thrown at v3/@claude-flow/cli/src/mcp-tools/agenticow-tools.ts:128
id: { type: 'integer', description: 'Explicit id (auto-assigned when omitted)' },
vector: { type: 'array', items: { type: 'number' }, description: 'Embedding vector (length must equal the memory dimension)' },
text: { type: 'string', description: 'Optional payload surfaced on query hits' },
},
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
- Pass records as an array with at least one element: [{ vector: [0.1, ...] }].
- If your batch is empty, skip the ingest call entirely rather than invoking with [].
- Guard the call site with Array.isArray(records) && records.length > 0 before invoking.
- Confirm each element is an object with a vector field (the next check, error 243, enforces that).
Example fix
// before
agenticow_ingest({ path, records: record })
// after
agenticow_ingest({ path, records: [record] }) Defensive patterns
Strategy: validation
Validate before calling
function validateIngestRecords(records) {
if (!Array.isArray(records) || records.length === 0) {
throw new Error('records must be a non-empty array');
}
return records;
} Type guard
function isIngestRecordArray(v: unknown): v is Array<{ vector: number[] }> {
return Array.isArray(v) && v.length > 0 && v.every((r) => r && typeof r === 'object' && Array.isArray((r as any).vector));
} Prevention
- Wrap a single record in an array literal at the call site.
- Skip the ingest call when the batch is empty rather than invoking with [].
- Type the parameter as Array<...> so the compiler rejects a bare object.
When it happens
Trigger: Calling agenticow_ingest with records omitted, null, a non-array value (object/string), or an empty array []. The JSON schema marks records as required, but runtime callers bypassing the schema still hit this.
Common situations: Passing records as a single object instead of an array; an upstream filter producing zero records; deserialisation yielding undefined when the field was absent.
Related errors
- candidate ${label} must ingest at least one vector
- each record requires a non-empty numeric vector
- scoreBy='nearest' requires a probe vector
- vector must be a non-empty numeric array
- Key exceeds maximum nesting depth of ${MAX_NESTING_DEPTH}
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/91a4c3cb994fa623.
Report an issue: GitHub.