mastra-ai/mastra · error · KnowledgeConflictError

Knowledge record version conflict: ${id}

Error message

Knowledge record version conflict: ${id}

What it means

updateNode performs optimistic concurrency control: the stored node's version must equal input.version. A mismatch means the node was modified (or merged) by someone else since the caller last read it, so the update is rejected with KnowledgeConflictError to prevent lost updates.

Source

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

        node =>
          !cursor ||
          node.updatedAt < cursor.updatedAt ||
          (node.updatedAt.getTime() === cursor.updatedAt.getTime() &&
            (node.name > cursor.name || (node.name === cursor.name && node.id > cursor.id))),
      )
      .slice(0, input.limit ?? 100)
      .map(cloneNode);
  }

  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(),

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Re-read the node (getNode) to get the current version and retry the update with it once
  2. Implement a retry loop around updateNode that refetches the version on KnowledgeConflictError (bounded retries)
  3. Serialize updates per node (queue/lock) if concurrent writers are common

Example fix

// before
await store.updateNode({ id, version: cachedVersion, description });
// after
let node = await store.getNode({ id, resolutionScope: scope });
for (let i = 0; i < 3; i++) {
  try { node = await store.updateNode({ id, version: node.version, description }); break; }
  catch (e) { if (e instanceof KnowledgeConflictError) node = await store.getNode({ id, resolutionScope: scope }); else throw e; }
}
Defensive patterns

Strategy: retry

Validate before calling

const current = await store.getNode({ id, resolutionScope: scope });
if (current.version !== cachedVersion) {
  // refresh your local copy before attempting the update
  cachedVersion = current.version;
}

Type guard

function isFresh(node: { version: number }, expectedVersion: number): boolean {
  return node.version === expectedVersion;
}

Try / catch

try {
  await store.updateNode({ id, version, ...patch });
} catch (e) {
  if (e instanceof KnowledgeConflictError) {
    const fresh = await store.getNode({ id, resolutionScope: scope });
    await store.updateNode({ id, version: fresh.version, ...patch });
  } else throw e;
}

Prevention

When it happens

Trigger: Calling updateNode({ id, version }) where existing.version !== input.version — e.g. two concurrent updates, an update after a mergeNodes bumped the version, or the caller cached a stale version across calls.

Common situations: Multiple agents/workflows editing the same knowledge node concurrently; long-running job holding a version while another request updates the node; retrying an update after a successful first attempt.

Related errors


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