mem0ai/mem0 · error · Error

HuggingFace embedBatch() returned ${embeddings.length} embed

Error message

HuggingFace embedBatch() returned ${embeddings.length} embeddings for ${texts.length} texts using model '${this.model}'

What it means

Thrown by HuggingFaceEmbedder.embedBatch() when the number of embeddings extracted from the response does not equal the number of input texts. Results are sorted by their index field then mapped; a count mismatch means the server dropped or duplicated rows, and returning them would silently mis-align vectors with texts. The message carries both counts and the model name. Empty input is short-circuited to [] before the request, so this only fires for non-empty batches.

Source

Thrown at mem0-ts/src/oss/src/embeddings/huggingface.ts:71

        `HuggingFace embed() returned no embeddings for model '${this.model}'`,
      );
    }
    return response.data[0].embedding;
  }

  async embedBatch(texts: string[]): Promise<number[][]> {
    if (texts.length === 0) {
      return [];
    }
    const response = await this.openai.embeddings.create({
      model: this.model,
      input: texts,
    });
    const embeddings = response.data
      .sort((a, b) => a.index - b.index)
      .map((item) => item.embedding);
    if (embeddings.length !== texts.length) {
      throw new Error(
        `HuggingFace embedBatch() returned ${embeddings.length} embeddings ` +
          `for ${texts.length} texts using model '${this.model}'`,
      );
    }
    return embeddings;
  }
}

View on GitHub (pinned to 001c235229)

Solutions

  1. Chunk the call below the TEI server's max batch size (default often 32-64): loop with slice
  2. Log the two counts from the message to confirm truncation (returned < sent almost always means batch-size cap)
  3. Increase TEI's --max-batch-size / --max-concurrent-requests if you control the server
  4. Retry once with backoff for transient server-side drops

Example fix

// before
const vecs = await embedder.embedBatch(chunks); // 500 chunks vs TEI max 32

// after
const vecs: number[][] = [];
for (let i = 0; i < chunks.length; i += 32) {
  vecs.push(...(await embedder.embedBatch(chunks.slice(i, i + 32))));
}
Defensive patterns

Strategy: retry

Validate before calling

const TEI_MAX_BATCH = 32; // match your TEI server's --max-batch-size
if (texts.length > TEI_MAX_BATCH) {
  // chunk upstream instead of letting the server truncate
}
for (let i = 0; i < texts.length; i += TEI_MAX_BATCH) {
  await embedder.embedBatch(texts.slice(i, i + TEI_MAX_BATCH));
}

Try / catch

try {
  vectors = await embedder.embedBatch(texts);
} catch (e) {
  if (e instanceof Error && /embedBatch\(\) returned \d+ embeddings/.test(e.message)) {
    // almost always server batch-size truncation: halve and retry
    const half = Math.ceil(texts.length / 2);
    vectors = [
      ...(await embedder.embedBatch(texts.slice(0, half))),
      ...(await embedder.embedBatch(texts.slice(half))),
    ];
  } else throw e;
}

Prevention

When it happens

Trigger: TEI server with a lower max batch size than the input array (extra rows silently truncated); response rows missing/malformed index fields causing dedupe or mis-sort; one input in the batch rejected server-side.

Common situations: Embedding large document chunk lists in one call exceeding TEI's --max-batch-size; mixing string lengths that trip server-side truncation rules.

Related errors


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