#7488·mem0

TypeScript: Gemini Embedding 2 batches collapse to one vector and lose memories

Author: xulongwu4Created Sep 28, 2026Updated Sep 29, 2026
Labelssdk-typescript

Component

TypeScript SDK

Summary

GoogleEmbedder.embedBatch() passes a string array as contents to @google/genai. For gemini-embedding-2, the SDK normalizes that array into one multipart content item and the API returns one combined vector, not one vector per text. Mem0 then assigns undefined to subsequent memory embeddings, causing failed vector inserts. The first memory can also receive a combined embedding instead of its own.

The implementation remains unchanged on upstream main 94c3fe9 (SDK package 3.3.1).

Steps to Reproduce

With a Google API key, compare these requests using @google/genai:

javascript
import { GoogleGenAI } from "@google/genai";
const ai = new GoogleGenAI({ apiKey: process.env.GOOGLE_API_KEY });
const texts = ["Apples are fruit.", "The sky is blue."];
for (const contents of [texts, texts.map(text => ({ parts: [{ text }] }))]) {
  const response = await ai.models.embedContent({
    model: "gemini-embedding-2",
    contents,
  });
  console.log(response.embeddings.length);
}
// Observed: 1, then 2

GoogleEmbedder.embedBatch(texts) currently uses the first request shape. An inferred Memory.add() extracting multiple facts can then log:

Failed to insert memory <id>: TypeError: Cannot read properties of undefined (reading 'length')

Expected Behavior

One separate embedding per input text, in order. Invalid/short embedding responses should be rejected so the existing per-text fallback can run.

Actual Behavior / How Verified

An AI coding agent ran live embedding-only requests with two harmless texts, then exercised the installed Memory.addToVectorStore and MemoryVectorStore against isolated in-memory SQLite, with controlled extraction and embedding responses. No existing memories were modified.

Actual live output:

json
{"inputTexts":2,"returnedEmbeddings":1,"dimensions":[3072]}
{"inputTexts":1,"returnedEmbeddings":1,"dimensions":[3072]}
{"model":"gemini-embedding-2","format":"explicit content objects","inputTexts":2,"returnedEmbeddings":2,"dimensions":[3072,3072]}
{"model":"gemini-embedding-001","format":"old model control","inputTexts":2,"returnedEmbeddings":2,"dimensions":[3072,3072]}

Isolated insertion results:

  • Two extracted memories + one embedding: 2 returned ADD results, 2 ADD history entries, 1 actual stored vector, and the exact .length error.
  • Two extracted memories + two embeddings: 2 results, 2 history entries, 2 stored vectors, no insert errors.

The history/result false-success behavior is a related core issue: insertion errors are caught but all records are still included in history/results. A focused Google-embedder patch can prevent this trigger; it should not claim to fix arbitrary vector-store insertion failures.

Environment

  • Runtime mem0ai: 3.1.7; same Google embedder code on upstream main (3.3.1)
  • @google/genai: 2.21.0
  • Node: 24.18.0
  • OS: Linux
  • Model: gemini-embedding-2

What Was Ruled Out

Credentials and single-text requests work. The same two-string request returns two embeddings with gemini-embedding-001. SQLite successfully stores both records when given both vectors. This is not user/project scoping.

Proposed Fix

Send separate Content objects for batch texts and validate response cardinality and missing/empty vectors before returning. Keep the existing model and stored data unchanged. Add mocked regressions for aggregation and malformed responses.

AI Assistance

AI found and wrote this, and I have not reproduced it myself. The agent ran the probes and will disclose automated verification separately from human review. Requesting maintainer acceptance before a review-ready PR.