{"record":{"id":"2daabc39e94b04c9","repo":"mastra-ai/mastra","slug":"knowledge-scope-exceeds-maxscope-ceiling","errorCode":null,"errorMessage":"Knowledge scope exceeds ${maxScope} ceiling","messagePattern":"Knowledge scope exceeds (.+?) ceiling","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/storage/domains/knowledge/base.ts","lineNumber":367,"sourceCode":" * @experimental\n */\nexport function assertKnowledgeDescriptionWithinBound(description: string | undefined): void {\n  if (description === undefined) return;\n  if (description.length > MAX_KNOWLEDGE_NODE_DESCRIPTION_LENGTH) {\n    throw new Error(\n      `Knowledge node description exceeds the ${MAX_KNOWLEDGE_NODE_DESCRIPTION_LENGTH} UTF-16 code unit limit`,\n    );\n  }\n}\n\nexport function assertKnowledgeScopeWithinCeiling(scope: KnowledgeScope, maxScope?: KnowledgeScopeLevel): void {\n  if (!maxScope) return;\n  const reservedLevels = scope\n    .map(entry => SCOPE_ORDER[entry.slice(0, entry.indexOf(':')) as KnowledgeScopeLevel])\n    .filter((value): value is number => value !== undefined);\n  const narrowestLevel = reservedLevels.length > 0 ? Math.max(...reservedLevels) : Number.MAX_SAFE_INTEGER;\n  if (narrowestLevel < SCOPE_ORDER[maxScope]) {\n    throw new Error(`Knowledge scope exceeds ${maxScope} ceiling`);\n  }\n}\n\nexport function assertKnowledgeCeilingRaised(\n  currentMaxScope: KnowledgeScopeLevel | undefined,\n  maxScope: KnowledgeScopeLevel | undefined,\n): void {\n  if (currentMaxScope && maxScope && SCOPE_ORDER[maxScope] > SCOPE_ORDER[currentMaxScope]) {\n    throw new Error(`Knowledge ceiling cannot be lowered from ${currentMaxScope} to ${maxScope}`);\n  }\n}\n\nexport function parseKnowledgeWikilinks(text: string): string[] {\n  const names: string[] = [];\n  const seen = new Set<string>();\n  let contentStart = -1;\n\n  for (let index = 0; index < text.length - 1; index++) {","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/storage/domains/knowledge/base.ts#L349-L385","documentation":"assertKnowledgeScopeWithinCeiling enforces a record's maxScope ceiling: the narrowest level reserved in the record's scope must not be narrower than the ceiling (scope levels are ordered org=0 < resource=1 < thread=2). If the scope reserves a level narrower than the allowed ceiling, the scope 'exceeds' the ceiling and the write/rescope is rejected. This keeps records from being pinned more narrowly than their visibility policy permits.","triggerScenarios":"appendKnowledge with maxScope:'resource' but scope containing 'thread:<id>'; rescopeKnowledge moving a record into a thread-level scope while its maxScope is 'org' or 'resource'; createKnowledgeWriteTools resolving a write scope narrower than the ceiling passed in input.","commonSituations":"Widening/narrowing a record via rescopeKnowledge without raising the ceiling first; an agent tool writing thread-scoped notes onto a record created with a stricter ceiling; defaulting maxScope to 'org' while composing thread-level scopes.","solutions":["Raise the record's ceiling first via raiseKnowledgeCeiling({ id, maxScope: 'thread' }), then rescope/append with the narrower scope.","Or keep the record's scope at or above its existing maxScope level (don't add thread entries when maxScope is 'resource').","Pass the intended maxScope consistently in AppendKnowledgeInput so scope and ceiling match at creation time.","Pre-check with SCOPE_ORDER semantics: narrowest scope level must be >= SCOPE_ORDER[maxScope]."],"exampleFix":"// before\nawait storage.rescopeKnowledge({ id, scope: [`org:o`, `resource:r`, `thread:t`] }); // maxScope 'resource'\n// after\nawait storage.raiseKnowledgeCeiling({ id, maxScope: 'thread' });\nawait storage.rescopeKnowledge({ id, scope: [`org:o`, `resource:r`, `thread:t`] });","handlingStrategy":"validation","validationCode":"const ORDER = { org: 0, resource: 1, thread: 2 } as const;\nfunction scopeWithinCeiling(scope: string[], maxScope?: keyof typeof ORDER): boolean {\n  if (!maxScope) return true;\n  const levels = scope.map(e => ORDER[e.slice(0, e.indexOf(':')) as keyof typeof ORDER]).filter((n): n is number => n !== undefined);\n  const narrowest = levels.length ? Math.max(...levels) : Number.MAX_SAFE_INTEGER;\n  return narrowest >= ORDER[maxScope];\n}","typeGuard":null,"tryCatchPattern":"try {\n  await storage.rescopeKnowledge({ id, scope });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('ceiling')) {\n    await storage.raiseKnowledgeCeiling({ id, maxScope: 'thread' });\n    await storage.rescopeKnowledge({ id, scope });\n  } else throw e;\n}","preventionTips":["Keep maxScope and scope consistent at creation time in AppendKnowledgeInput.","Raise the ceiling before any rescope to a narrower level.","Remember: org(0) is widest, thread(2) is narrowest; narrowest scope level must be >= ceiling order."],"tags":["knowledge","scope","ceiling","authorization"],"backgroundTag":"scope-ceiling-violation","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}