mastra-ai/mastra · error
Node must have an embedding
Error message
Node must have an embedding
What it means
GraphRAG's addNode requires every node to carry an embedding vector, since similarity edges and graph traversal are computed from embeddings. If node.embedding is falsy (undefined/null/empty), the node cannot participate and the method throws. It is a structural precondition of building the graph.
Source
Thrown at packages/rag/src/graph-rag/index.ts:69
const GRAPH_RAG_SNAPSHOT_VERSION = 1;
export class GraphRAG {
private nodes: Map<string, GraphNode>;
private edges: GraphEdge[];
private dimension: number;
private threshold: number;
constructor(dimension: number = 1536, threshold: number = 0.7) {
this.nodes = new Map();
this.edges = [];
this.dimension = dimension;
this.threshold = threshold;
}
// Add a node to the graph
addNode(node: GraphNode): void {
if (!node.embedding) {
throw new Error('Node must have an embedding');
}
if (node.embedding.length !== this.dimension) {
throw new Error(`Embedding dimension must be ${this.dimension}`);
}
this.nodes.set(node.id, node);
}
// Add an edge between two nodes
addEdge(edge: GraphEdge): void {
if (!this.nodes.has(edge.source) || !this.nodes.has(edge.target)) {
throw new Error('Both source and target nodes must exist');
}
this.edges.push(edge);
// Add reverse edge
this.edges.push({
source: edge.target,
target: edge.source,
weight: edge.weight,View on GitHub (pinned to 75dd419e61)
Solutions
- Embed all documents first with embedMany (or via MDocument.embed) and attach results: { ...doc, embedding: embeddings[i] }.
- Filter out nodes lacking embeddings before calling addNode/createGraph.
- Check your embedding step for silent failures (empty response arrays, rate-limit partials).
- If a node legitimately has no embedding, exclude it from the graph rather than passing null.
Example fix
// before
nodes.forEach(n => graph.addNode({ id: n.id, content: n.text }));
// after
const { embeddings } = await embedMany({ model, values: nodes.map(n => n.text) });
nodes.forEach((n, i) => graph.addNode({ id: n.id, content: n.text, embedding: embeddings[i] })); Defensive patterns
Strategy: validation
Validate before calling
function assertEmbeddings(nodes: { id: string; embedding?: number[] }[]): void {
const missing = nodes.filter(n => !n.embedding || n.embedding.length === 0);
if (missing.length) throw new Error(`Nodes missing embeddings: ${missing.map(n => n.id).join(', ')}`);
} Type guard
function hasEmbedding(n: GraphNode): n is GraphNode & { embedding: number[] } {
return Array.isArray(n.embedding) && n.embedding.length > 0;
} Try / catch
try {
nodes.forEach(n => graph.addNode(n));
} catch (e) {
if ((e as Error).message === 'Node must have an embedding') {
console.error('A node reached addNode without an embedding; re-run the embed step');
}
throw e;
} Prevention
- Always run embedMany/upsert and attach embeddings before building the graph.
- Filter nodes with !embedding before createGraph.
- Assert embedding presence in your ingestion pipeline tests.
- Check embed results for empty/partial arrays after API calls.
When it happens
Trigger: Calling graph.addNode(node) or createGraph({ nodes }) where some nodes were constructed without an embedding field, or where embedding generation (embedMany/upsert step) silently failed or was skipped.
Common situations: Mixing documents that were embedded with raw records loaded from a database; a failed embed() step returning partial results; hand-building GraphNode objects for tests without embeddings; deserializing old/partial data (though deserialize filters).
Related errors
- Embedding dimension must be ${this.dimension}
- Both source and target nodes must exist
- Chunks and embeddings must have the same length
- HTML chunking requires either headers or sections to be spec
- JSON chunking requires maxSize to be specified
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/022ac40a39f08617.
Report an issue: GitHub.