mem0ai/mem0 · error · Error

ids and vectors must have the same length

Error message

ids and vectors must have the same length

What it means

insert() performs an executeMany INSERT of (id, vector, payload) rows and requires the ids array to align one-to-one with the vectors array. A length mismatch means rows would reference undefined ids or vectors, so it fails fast before any SQL runs. Zero-length input is fine (early return).

Source

Thrown at mem0-ts/src/oss/src/vector_stores/oracledb.ts:577

  private vectorBind(vector: number[]) {
    return {
      type: this.oracledb.DB_TYPE_VECTOR,
      val: new Float32Array(vector),
    };
  }

  private payloadBind(payload: Record<string, any>) {
    return { type: this.oracledb.DB_TYPE_JSON, val: payload };
  }

  async insert(
    vectors: number[][],
    ids: string[],
    payloads: Record<string, any>[],
  ): Promise<void> {
    if (ids.length !== vectors.length) {
      throw new Error("ids and vectors must have the same length");
    }
    if (payloads.length !== vectors.length) {
      throw new Error("payloads and vectors must have the same length");
    }

    if (vectors.length === 0) return;

    await this.initialize();

    await this.withConnection(async (connection) => {
      await connection.executeMany(
        `INSERT INTO ${this.collectionName} (id, vector, payload) VALUES (:id, :vector, :payload)`,
        vectors.map((vector, i) => ({
          id: ids[i],
          vector: new Float32Array(vector),
          payload: payloads[i] ?? {},
        })) as BindParameters[],
        {

View on GitHub (pinned to 001c235229)

Solutions

  1. Build ids and vectors from the same source loop so lengths match by construction: items.map(i => [i.id, embed(i.text)]).
  2. Add an assert before insert: if (ids.length !== vectors.length) throw new RangeError(...) with context.
  3. Re-derive arrays together after filtering: keep an array of {id, vector} tuples and unzip at the end.
  4. Check for accidental .slice()/.splice() on one array during batching.

Example fix

// before
const ids = items.map((i) => i.id).filter(Boolean); // one item had no id
await store.insert(vectors, ids, payloads);

// after
const rows = items.filter((i) => i.id);
await store.insert(rows.map((r) => embed(r.text)), rows.map((r) => r.id), rows.map((r) => r.payload));
Defensive patterns

Strategy: validation

Validate before calling

function assertInsertArity(ids: string[], vectors: number[][], payloads: Record<string, any>[]): void {
  if (ids.length !== vectors.length) throw new RangeError(`ids(${ids.length}) != vectors(${vectors.length})`);
  if (payloads.length !== vectors.length) throw new RangeError(`payloads(${payloads.length}) != vectors(${vectors.length})`);
}

Type guard

type InsertRow = { id: string; vector: number[]; payload: Record<string, any> };
const isAlignedRows = (rows: InsertRow[]): boolean =>
  rows.every((r) => typeof r.id === 'string' && Array.isArray(r.vector) && !!r.payload);

Try / catch

try { await store.insert(vectors, ids, payloads); } catch (e) { if (e instanceof Error && e.message.includes('same length')) { /* rebuild the three arrays from the same source rows and retry the batch */ } else throw e; }

Prevention

When it happens

Trigger: Direct calls to the vector store's insert(vectors, ids, payloads) where ids were deduplicated, filtered, or chunked independently of vectors; internal Memory.add() flows producing ids via uuid per vector where one array was built in a loop with an off-by-one.

Common situations: Custom ingestion scripts batching embeddings then mapping ids with .filter() or .slice() applied to only one array; retry logic that drops failed ids but keeps all vectors; passing ids.length = vectors.length - 1 due to a sparse index skip.

Related errors


AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15). Data as JSON: /api/errors/368ab5291721e6ec. Report an issue: GitHub.