mastra-ai/mastra · error

Batch embedder returned no embedding for input text.

Error message

Batch embedder returned no embedding for input text.

What it means

The configured embedder is a batch-capable embedder (branded with `batch: true`), and `#embedOne` dispatched the single text as a one-element array, but the returned embeddings array was empty — no embedding came back for the input. This indicates a misbehaving embedder implementation rather than a configuration problem.

Source

Thrown at packages/core/src/workspace/search/search-engine.ts:687

      return 'bm25';
    }

    throw new Error('No search configuration available. Provide bm25 or vector config.');
  }

  /**
   * Embed a single text, dispatching to the batch path with a one-element array
   * when the configured embedder is batch-capable.
   */
  async #embedOne(text: string): Promise<number[]> {
    if (!this.#vectorConfig) {
      throw new Error('Vector configuration is required to embed text.');
    }
    const { embedder } = this.#vectorConfig;
    if (isBatchEmbedder(embedder)) {
      const [embedding] = await embedder([text]);
      if (!embedding) {
        throw new Error('Batch embedder returned no embedding for input text.');
      }
      return embedding;
    }
    return embedder(text);
  }

  /**
   * Embed many texts. Uses a single batched call (chunked by `maxBatchSize`)
   * when the embedder is batch-capable; otherwise falls back to parallel
   * single-text calls.
   */
  async #embedAll(texts: string[]): Promise<number[][]> {
    if (!this.#vectorConfig) {
      throw new Error('Vector configuration is required to embed texts.');
    }
    if (texts.length === 0) return [];

    const { embedder } = this.#vectorConfig;

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Fix the batch embedder implementation so it always returns exactly one embedding per input text, in order (verify the `embedMany` result: `return embeddings`, not a nested/destructured value).
  2. Add an assertion in your embedder: throw if `embeddings.length !== texts.length`.
  3. If the provider can silently drop inputs, fall back to a single-text embedder (omit the `batch: true` brand) so each call gets one result.

Example fix

// before — drops texts, returns fewer embeddings
const embedder: BatchEmbedder = Object.assign(
  async (texts) => {
    const { embeddings } = await embedMany({ model, values: texts.filter(Boolean) });
    return embeddings;
  },
  { batch: true as const },
);

// after — 1:1 with input, validated
const embedder: BatchEmbedder = Object.assign(
  async (texts) => {
    const { embeddings } = await embedMany({ model, values: texts });
    if (embeddings.length !== texts.length) {
      throw new Error('Embedding count mismatch');
    }
    return embeddings;
  },
  { batch: true as const },
);
Defensive patterns

Strategy: type-guard

Validate before calling

function assertValidBatchEmbedder(e: Embedder): asserts e is BatchEmbedder {
  if (!isBatchEmbedder(e)) return;
  // smoke-test in dev: batch embedder must return 1:1 results
}
// at construction:
const probe = await embedder(['ping']);
if (probe.length !== 1) throw new Error('Batch embedder violates 1:1 contract');

Type guard

function isWellFormedBatchEmbedder(e: Embedder): e is BatchEmbedder {
  return isBatchEmbedder(e) && typeof e === 'function';
}

Try / catch

try {
  const vec = await engine.queryEmbedding(text);
} catch (e) {
  if (e instanceof Error && e.message.includes('Batch embedder returned no embedding')) {
    // rebuild engine with a single-text embedder or fixed batch embedder
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: A `BatchEmbedder` whose implementation returns an array shorter than its input (e.g. `embedMany` result destructured incorrectly, empty array returned for empty/filtered input, provider dropping a text) reached via `embedding(text)` or `queryEmbedding(text)`.

Common situations: Custom embedder wrappers that filter out blank strings and return fewer results; a provider returning zero embeddings on API error without throwing; hand-rolled `Object.assign(fn, { batch: true })` where `fn` doesn't preserve input order/count.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/22489fcbbd029185. Report an issue: GitHub.