mastra-ai/mastra · error · Error
Updating node content requires expectedVersion.
Error message
Updating node content requires expectedVersion.
What it means
When the node upsert targets an existing node, the tool requires expectedVersion to perform the content update, since updateNode relies on version-based optimistic concurrency to prevent lost updates. Omitting it on an existing node throws this error before touching storage.
Source
Thrown at packages/memory/src/processors/observational-memory/subconscious/knowledge-write-tools.ts:263
throw new Error(`capture-guidance is limited to ${MAX_GUIDANCE_LENGTH} characters.`);
}
const store = await getStore(memory);
const scope = resolveWriteScope(options, value.scope);
const resolvedNode = await store.resolveNode({ name, scope });
const existing =
resolvedNode && knowledgeScopeKey(resolvedNode.scope) === knowledgeScopeKey(scope) ? resolvedNode : null;
if (!existing) {
if (value.expectedVersion !== undefined)
throw new Error('expectedVersion is only valid for an existing node.');
return store.createNode({
name,
kind: value.kind ?? 'document',
content: value.content,
scope,
resolutionScope: options.scope,
});
}
if (value.expectedVersion === undefined) throw new Error('Updating node content requires expectedVersion.');
return store.updateNode({
id: existing.id,
version: value.expectedVersion,
kind: value.kind,
content: value.content,
resolutionScope: options.scope,
});
},
}),
};
}
View on GitHub (pinned to 75dd419e61)
Solutions
- Fetch the current node via store.resolveNode({ name, scope }) and pass its version as expectedVersion
- Use knowledge_update_node-style flows that always carry expectedVersion for existing nodes
- In code, branch: resolve first; create without version if absent, update with version if present
Example fix
// before
await tool.execute({ name, content });
// after
const existing = await store.resolveNode({ name, scope });
await tool.execute({ name, content, expectedVersion: existing?.version }); Defensive patterns
Strategy: validation
Validate before calling
const existing = await store.resolveNode({ name, scope });
const input = existing
? { name, content, expectedVersion: existing.version }
: { name, content }; Try / catch
try {
await tool.execute(input);
} catch (e) {
if (e instanceof Error && e.message.includes('requires expectedVersion')) {
const node = await store.resolveNode({ name, scope });
await tool.execute({ ...input, expectedVersion: node.version });
} else throw e;
} Prevention
- Always resolve before upsert so update paths carry expectedVersion
- Treat version as required for any write to an existing node
- Retry on version conflicts by refetching the node
When it happens
Trigger: Calling the upsert tool with a name that resolves to an existing node in the same scope but without expectedVersion in the input.
Common situations: Reusable code paths that always omit expectedVersion; a node created between your check and your write so your create path flips into an update path; hand-written tool calls from the LLM missing the field.
Related errors
- expectedVersion is only valid for an existing node.
- MastraClient.deleteThread() requires exactly one of agentId
- Thread ID is required for thread-scoped working memory updat
- Resource ID is required for resource-scoped working memory u
- Thread with id ${threadId} resourceId does not match the cur
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/56450544e2189a5b.
Report an issue: GitHub.