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

  1. Use a unique id (default generation) or check existence with getNode/list first and skip creation if present
  2. If the existing node is equivalent, treat creation as idempotent: fetch and return the existing node instead
  3. 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

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


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