mastra-ai/mastra · error

Knowledge node already exists in scope: ${name}

Error message

Knowledge node already exists in scope: ${name}

What it means

updateNode tried to rename and/or re-scope a node such that the resulting (name, scope) key collides with a different existing node (collision id differs from the node being updated). Names must be unique per scope, so the store rejects the rename.

Source

Thrown at packages/core/src/storage/domains/knowledge/inmemory.ts:215

  }

  async updateNode(input: UpdateKnowledgeNodeInput): Promise<KnowledgeNode> {
    return this.#runAtomicMutation(() => this.#updateNode(input));
  }

  #updateNode(input: UpdateKnowledgeNodeInput): KnowledgeNode {
    assertKnowledgeDescriptionWithinBound(input.description);
    const existing = this.#db.knowledgeNodes.get(input.id);
    if (!existing) throw new KnowledgeNotFoundError('node', input.id);
    if (existing.version !== input.version) throw new KnowledgeConflictError(input.id);
    if (existing.mergedInto) throw new Error(`Cannot update merged knowledge node: ${input.id}`);

    const scope = canonicalizeKnowledgeScope(input.scope ?? existing.scope);
    const name = (input.name ?? existing.name).trim();
    const oldKey = recordKey(existing.name, existing.scope);
    const newKey = recordKey(name, scope);
    const collision = this.#db.knowledgeNodeKeys.get(newKey);
    if (collision && collision !== input.id) throw new Error(`Knowledge node already exists in scope: ${name}`);

    const updated: KnowledgeNode = {
      ...existing,
      name,
      kind: input.kind ?? existing.kind,
      content: input.content ?? existing.content,
      description: input.description ?? existing.description,
      scope,
      version: existing.version + 1,
      updatedAt: new Date(),
    };
    if (oldKey !== newKey) {
      this.#db.knowledgeNodeKeys.delete(oldKey);
      this.#db.knowledgeNodeKeys.set(newKey, input.id);
    }
    this.#db.knowledgeNodes.set(input.id, updated);
    if (input.content !== undefined || input.name !== undefined || input.scope !== undefined) {
      this.#replaceMentions('node', input.id, updated.content ?? '', input.resolutionScope ?? scope, scope);

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Pick a different name, or a different target scope where the name is free
  2. Check for a name collision first (list/find nodes by name in the target scope) and merge instead of renaming if a duplicate exists
  3. Delete or rename the colliding node first if it is truly obsolete

Example fix

// before
await store.updateNode({ id, version, name: 'existing-name', scope });
// after
const dup = await store.findNodesByName?.('existing-name');
if (dup?.length) await store.mergeNodes({ sourceId: id, targetId: dup[0].id, sourceVersion: version });
else await store.updateNode({ id, version, name: 'existing-name', scope });
Defensive patterns

Strategy: validation

Validate before calling

const collision = db.knowledgeNodeKeys.get(recordKey(newName, newScope));
if (collision && collision !== id) throw new Error(`name '${newName}' already used in scope`);

Type guard

function isNameFree(nameKey: string, selfId: string, keys: Map<string, string>): boolean {
  const hit = keys.get(nameKey);
  return hit === undefined || hit === selfId;
}

Try / catch

try {
  await store.updateNode({ id, version, name: newName, scope });
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Knowledge node already exists in scope')) {
    await mergeOrCreateWithSuffix(id, newName, scope);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling updateNode with input.name and/or input.scope whose recordKey(name, scope) is already mapped in knowledgeNodeKeys to another node id (collision !== input.id).

Common situations: Renaming a node to a name already used by a sibling in the same scope; moving a node into a scope where that name exists; bulk renames racing with node creation.

Related errors


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