{"record":{"id":"27285cda10272b32","repo":"mastra-ai/mastra","slug":"merged-knowledge-node-is-not-visible-from-scope","errorCode":null,"errorMessage":"Merged knowledge node is not visible from scope: ${input.name}","messagePattern":"Merged knowledge node is not visible from scope: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/storage/domains/knowledge/inmemory.ts","lineNumber":110,"sourceCode":"    this.#db.knowledgeCursors.clear();\n    this.#db.knowledgeActivity.length = 0;\n    this.#db.knowledgeSemanticOutbox.clear();\n    this.#db.knowledgeSemanticIdempotency.clear();\n  }\n\n  async createNode(input: CreateKnowledgeNodeInput): Promise<KnowledgeNode> {\n    return this.#runAtomicMutation(() => this.#createNode(input));\n  }\n\n  #createNode(input: CreateKnowledgeNodeInput): KnowledgeNode {\n    assertKnowledgeDescriptionWithinBound(input.description);\n    const scope = canonicalizeKnowledgeScope(input.scope);\n    const key = recordKey(input.name, scope);\n    const existingId = this.#db.knowledgeNodeKeys.get(key);\n    if (existingId) {\n      const terminal = this.#resolveTerminalNode(existingId)!;\n      if (!isKnowledgeScopeVisible(terminal.scope, scope)) {\n        throw new Error(`Merged knowledge node is not visible from scope: ${input.name}`);\n      }\n      return cloneNode(terminal);\n    }\n\n    const now = new Date();\n    const node: KnowledgeNode = {\n      id: input.id ?? crypto.randomUUID(),\n      type: 'node',\n      name: input.name.trim(),\n      kind: input.kind,\n      content: input.content,\n      description: input.description,\n      scope,\n      version: 1,\n      createdAt: now,\n      updatedAt: now,\n    };\n    if (this.#db.knowledgeNodes.has(node.id)) throw new Error(`Knowledge node already exists: ${node.id}`);","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/storage/domains/knowledge/inmemory.ts#L92-L128","documentation":"createNode found an existing knowledge node registered under the same name+scope key, and that node has been merged (mergedInto set) into another node. The merged terminal node's scope is not visible from the scope the caller is creating in, so instead of silently returning the terminal node the store refuses the operation. This prevents resolving a merge through a scope the caller cannot see.","triggerScenarios":"Calling createNode() with a name whose (name, scope) key maps to a node id whose terminal (post-merge-resolution) node has a scope that isKnowledgeScopeVisible() evaluates as not visible from the requested input.scope. Happens when the original node was merged into a node with a narrower or otherwise non-visible scope.","commonSituations":"Re-creating a node name after it was merged into a node scoped more narrowly (e.g. merged into a resource-scoped node while creating at tenant scope); cross-tenant/workflow merges that changed scope visibility; stale client code assuming the old node still exists at its original scope.","solutions":["Fetch the merge chain (getNode on the existing id) to find the terminal node and reference it directly instead of creating a new node with the same name","Create the node under a different name or in a scope where the merged terminal node is visible","Un-merge or re-merge the target so its scope is visible from the creation scope (merge into a node whose scope is broader or equal)","If the key is stale/corrupt, delete the knowledge record so the key is freed before recreating"],"exampleFix":"// before\nawait store.createNode({ name: 'billing-policy', scope, ... });\n// after\nconst existing = store.findNodesByName?.('billing-policy') ?? [];\nconst node = existing.length\n  ? await store.getNode({ id: existing[0].id, resolutionScope: scope })\n  : await store.createNode({ name: 'billing-policy', scope, ... });","handlingStrategy":"validation","validationCode":"const existingId = db.knowledgeNodeKeys.get(recordKey(name, canonicalizeKnowledgeScope(scope)));\nif (existingId) {\n  const terminal = resolveTerminal(existingId);\n  if (!isKnowledgeScopeVisible(terminal.scope, scope)) throw new Error(`skip: merged node '${name}' not visible from scope`);\n}","typeGuard":"function isMergedNodeVisible(terminal: { scope: KnowledgeScope }, scope: KnowledgeScope): boolean {\n  return isKnowledgeScopeVisible(terminal.scope, scope);\n}","tryCatchPattern":"try {\n  node = await store.createNode({ name, scope });\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Merged knowledge node is not visible from scope')) {\n    node = await resolveByNameOrCreateWithSuffix(name, scope);\n  } else throw e;\n}","preventionTips":["Before creating a node, check whether the name already exists and follow any mergedInto chain to its terminal","Keep merge targets at equal or broader scopes than sources so terminals stay visible","Avoid mixing tenants/scopes when deduplicating knowledge nodes","Log scope visibility failures to catch scope-design problems early"],"tags":["knowledge-store","scope-visibility","merge-conflict","inmemory"],"backgroundTag":"knowledge-node-scope-not-visible","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}