{"record":{"id":"24cc4d0694be6054","repo":"mastra-ai/mastra","slug":"label-is-outside-the-curator-s-visible-scope","errorCode":null,"errorMessage":"${label} is outside the curator's visible scope.","messagePattern":"(.+?) is outside the curator's visible scope\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/memory/src/processors/observational-memory/subconscious/knowledge-write-tools.ts","lineNumber":44,"sourceCode":"  defaultScope: KnowledgeScopeLevel;\n  maxScope?: KnowledgeScopeLevel;\n}\n\nasync function getStore(memory: KnowledgeWriteToolsMemory): Promise<KnowledgeStorage> {\n  const store = await memory.storage.getStore('knowledge');\n  if (!store) throw new Error('Knowledge write tools require a configured knowledge storage domain.');\n  return store;\n}\n\nfunction resolveWriteScope(options: KnowledgeWriteToolsOptions, level?: KnowledgeScopeLevel): KnowledgeScope {\n  const scope = expandKnowledgeScope(options.scope, level ?? options.defaultScope);\n  assertKnowledgeScopeWithinCeiling(scope, options.maxScope);\n  return scope;\n}\n\nfunction requireVisible(scope: KnowledgeScope, options: KnowledgeWriteToolsOptions, label: string): void {\n  if (!isKnowledgeScopeVisible(scope, options.scope)) {\n    throw new Error(`${label} is outside the curator's visible scope.`);\n  }\n}\n\nexport function createKnowledgeWriteTools(\n  memory: KnowledgeWriteToolsMemory,\n  options: KnowledgeWriteToolsOptions,\n): Record<string, ToolAction<any, any, any>> {\n  return {\n    knowledge_append: createTool({\n      id: 'knowledge_append',\n      description: 'Append a scoped record to an existing node. Provenance and capture time are stamped by code.',\n      inputSchema: {\n        type: 'object',\n        properties: {\n          node: { type: 'string', minLength: 1 },\n          text: { type: 'string', minLength: 1 },\n          scope: scopeLevelSchema,\n          when: { type: 'string' },","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/memory/src/processors/observational-memory/subconscious/knowledge-write-tools.ts#L26-L62","documentation":"Curator write tools operate only on entities visible inside the curator's configured scope (options.scope, itself bounded by options.maxScope). requireVisible checks a node's or record's stored scope against that visibility window using isKnowledgeScopeVisible and throws a labeled error naming the entity ('Knowledge node', 'KnowledgeRecord', 'Knowledge merge source/target') when it falls outside. This enforces multi-tenant isolation: a curator must never mutate knowledge belonging to another org, resource, or thread.","triggerScenarios":"Calling knowledge_append/knowledge_update_node/knowledge_remove/etc. with a node or recordId whose stored scope key is broader or different from the curator's resolution scope — e.g. a thread-scoped curator trying to touch an org-level node, or an ID referencing another tenant's entity.","commonSituations":"Cross-tenant IDs leaked into prompts or copied between environments; curators instantiated with a narrow (thread/resource) scope but agents supplying org-scoped node IDs; scope ceiling (maxScope) lowered after records were created at higher levels.","solutions":["Use node/record IDs that were created within the curator's scope; re-resolve by name in the current scope instead of reusing foreign IDs.","Widen options.scope (or maxScope) in createKnowledgeWriteTools if the curator legitimately needs broader visibility.","Verify the tenant coordinates (org/resource/thread) used to build options.scope match the data's origin.","Check isKnowledgeScopeVisibility semantics: visibility means the stored scope is at or below the curator's window at the same coordinates."],"exampleFix":"// before\nconst tools = createKnowledgeWriteTools(memory, {\n  scope: ['org:org_1', 'resource:r1', 'thread:t1'], // thread-scoped curator\n  sourceThreadId: 't1', defaultScope: 'thread',\n});\nawait tools.knowledge_append.execute({ node: 'org_level_node', text: 'x' }, {} as any); // throws\n// after\ncreateKnowledgeWriteTools(memory, {\n  scope: ['org:org_1', 'resource:r1', 'thread:t1'],\n  maxScope: 'org', // allow org-level visibility if intended\n  sourceThreadId: 't1', defaultScope: 'org',\n});","handlingStrategy":"try-catch","validationCode":"import { isKnowledgeScopeVisible } from '@mastra/core/storage';\n// before calling a write tool with a known entity scope:\nif (!isKnowledgeScopeVisible(entityScope, curatorOptions.scope)) {\n  throw new Error('Target entity is not visible to this curator.');\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await curatorTools.knowledge_append.execute(args, {} as any);\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"outside the curator's visible scope\")) {\n    return { success: false, reason: 'scope-violation', label: e.message.split(' ')[0] };\n  }\n  throw e;\n}","preventionTips":["Only pass node/record IDs obtained from reads within the same scope.","Keep maxScope consistent with the data's creation scopes.","Never share entity IDs across tenants or environments.","Log scope keys (knowledgeScopeKey) alongside IDs to ease debugging."],"tags":["scope-visibility","authorization","knowledge-write-tools","multi-tenancy"],"backgroundTag":"resource-out-of-scope","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}