mastra-ai/mastra · error
Knowledge node already exists: ${node.id}
Error message
Knowledge node already exists: ${node.id} What it means
The store attempted to insert a newly built KnowledgeNode whose generated id is already present in the knowledgeNodes map. Because node ids are normally freshly generated, this indicates an id collision — typically from a caller-supplied id, deterministic id generation, or a corrupted/desynchronized in-memory database.
Source
Thrown at packages/core/src/storage/domains/knowledge/inmemory.ts:128
throw new Error(`Merged knowledge node is not visible from scope: ${input.name}`);
}
return cloneNode(terminal);
}
const now = new Date();
const node: KnowledgeNode = {
id: input.id ?? crypto.randomUUID(),
type: 'node',
name: input.name.trim(),
kind: input.kind,
content: input.content,
description: input.description,
scope,
version: 1,
createdAt: now,
updatedAt: now,
};
if (this.#db.knowledgeNodes.has(node.id)) throw new Error(`Knowledge node already exists: ${node.id}`);
this.#db.knowledgeNodes.set(node.id, node);
this.#db.knowledgeNodeKeys.set(key, node.id);
this.#replaceMentions('node', node.id, node.content ?? '', input.resolutionScope ?? scope, scope);
this.#recordActivity('node-created', 'node', node.id, scope);
this.#enqueue('node', node.id, 'upsert', node.version, scope);
return cloneNode(node);
}
async getNode(id: string): Promise<KnowledgeNode | null> {
const node = this.#db.knowledgeNodes.get(id);
return node ? cloneNode(node) : null;
}
async getNodeByName({ name, scope }: { name: string; scope: KnowledgeScope }): Promise<KnowledgeNode | null> {
const id = this.#db.knowledgeNodeKeys.get(recordKey(name, scope));
if (!id) return null;
const node = this.#db.knowledgeNodes.get(id);
return node ? cloneNode(node) : null;View on GitHub (pinned to 75dd419e61)
Solutions
- Use a unique id (default generation) or check existence with getNode/list first and skip creation if present
- If the existing node is equivalent, treat creation as idempotent: fetch and return the existing node instead
- Rebuild or reseed the in-memory store so id and key indexes are consistent
Example fix
// before
await store.createNode({ id: 'node-1', name: 'policy', scope });
// after
const existing = await store.getNode({ id: 'node-1', resolutionScope: scope }).catch(() => null);
const node = existing ?? await store.createNode({ name: 'policy', scope }); Defensive patterns
Strategy: validation
Validate before calling
const dup = await store.listNodes?.({ scope });
if (dup?.some(n => n.name === name)) throw new Error(`node '${name}' already exists in scope`); Type guard
function isNodeAbsent(store: KnowledgeStore, id: string): boolean {
return !store.hasNode?.(id);
} Try / catch
try {
node = await store.createNode(input);
} catch (e) {
if (e instanceof Error && e.message.startsWith('Knowledge node already exists')) {
node = await store.getNode({ id: extractId(e.message), resolutionScope: input.scope });
} else throw e;
} Prevention
- Do not pass caller-supplied ids unless idempotent re-creation is intended
- Make create flows idempotent: fetch-by-name first, create only if missing
- Seed the store once; guard seed scripts with existence checks
- Regenerate ids per creation; never reuse ids from exported snapshots without clearing the store
When it happens
Trigger: Calling createNode() with input that produces a node.id already present in #db.knowledgeNodes (e.g. custom id generation, replaying a recorded create, or an in-memory DB rebuilt inconsistently so the name-key index missed the existing node).
Common situations: Importing/exporting knowledge data across store instances; replaying event logs; deterministic/test id generators reused across creations; seeding the store twice in the same process.
Related errors
- Merged knowledge node is not visible from scope: ${input.nam
- Knowledge node not found: ${id}
- Factory decisions require unique idempotency keys.
- Failed to unlink repository (${res.status})
- Failed to delete Factory (${res.status})
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/a4735c1d1369a345.
Report an issue: GitHub.