mastra-ai/mastra · error

Embedder returned no vector for ${entry.documentId}

Error message

Embedder returned no vector for ${entry.documentId}

What it means

`#apply` in packages/memory/src/processors/observational-memory/subconscious/semantic-index.ts:172 embeds a knowledge document's text to upsert it into the vector index. It throws a plain Error when the embedder resolves with no vector for that document, identifying the culprit as `entry.documentId`. The document cannot be indexed at all without its vector.

Source

Thrown at packages/memory/src/processors/observational-memory/subconscious/semantic-index.ts:172

  }

  async #apply(entry: KnowledgeSemanticOutboxEntry): Promise<void> {
    if (entry.operation === 'delete') {
      await this.#deleteDocument(entry.documentId);
      return;
    }

    const document = await this.#loadDocument(entry);
    if (!document) {
      await this.#deleteDocument(entry.documentId);
      return;
    }
    const result = await this.#embedder.doEmbed({
      values: [document.text],
      ...(this.#embedderOptions ?? {}),
    } as never);
    const embedding = result.embeddings[0];
    if (!embedding?.length) throw new Error(`Embedder returned no vector for ${entry.documentId}`);
    const indexName = this.#indexName(embedding.length);
    const indexes = await this.#knowledgeIndexes();
    if (!indexes.includes(indexName)) {
      await this.#vector.createIndex({ indexName, dimension: embedding.length });
    }
    for (const existingIndex of indexes) {
      if (existingIndex !== indexName) {
        await this.#vector.deleteVectors({ indexName: existingIndex, ids: [entry.documentId] });
      }
    }
    await this.#vector.upsert({
      indexName,
      ids: [entry.documentId],
      vectors: [embedding],
      metadata: [this.#metadata(document)],
    });
  }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Fix or replace the embedder so it returns a non-empty vector per value; check provider logs/quota.
  2. Validate document text before capture (non-empty, within size limits, no content that trips provider filters).
  3. Inspect the failing documentId's text in the store and embed it manually to reproduce.
  4. The failed entry is released back to the outbox, so retry after fixing the embedder.

Example fix

// before (empty text reaches the embedder)
await capture({ id: 'doc1', text: truncatedToEmpty(doc.text) });
// after
const text = doc.text?.trim();
if (!text) return; // skip empty documents instead of failing the drain
await capture({ id: 'doc1', text });
Defensive patterns

Strategy: validation

Validate before calling

const text = document.text?.trim();
if (!text) throw new Error(`Refusing to index empty document ${document.id}`);
if (text.length > MAX_EMBED_CHARS) throw new Error(`Document ${document.id} exceeds embedder limit`);

Type guard

function isEmbeddableDocument(doc) {
  return typeof doc?.text === 'string' && doc.text.trim().length > 0;
}

Try / catch

try {
  await indexingPipeline.flush();
} catch (e) {
  if (e.message.startsWith('Embedder returned no vector for')) {
    const docId = e.message.split('for ')[1];
    logger.error(`embedder returned no vector for ${docId}; quarantining document`);
    await quarantineDocument(docId); // keep the drain moving
    return indexingPipeline.flush();
  }
  throw e;
}

Prevention

When it happens

Trigger: During outbox drain, `doEmbed({ values: [document.text] })` returns `{ embeddings: [] }` or an empty first vector — provider content filter rejecting the text, empty/whitespace document text, a broken custom embedder, or an adapter silently resolving empty on quota exhaustion.

Common situations: Documents containing content the embedding provider refuses (safety filters); empty text after preprocessing/truncation bugs; custom embedder wrappers with the wrong return shape; provider outage that resolves instead of rejecting.

Related errors


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