mastra-ai/mastra · error · Error
Knowledge scope contains multiple ${level} entries
Error message
Knowledge scope contains multiple ${level} entries What it means
A knowledge scope may contain at most one entry per level (one org, one resource, one thread). canonicalizeKnowledgeScope detects two distinct entries at the same level and throws this error; identical duplicate entries are silently deduplicated.
Source
Thrown at packages/core/src/storage/domains/knowledge/base.ts:287
}
const SCOPE_ORDER: Record<KnowledgeScopeLevel, number> = { org: 0, resource: 1, thread: 2 };
const CROCKFORD = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
let lastUlidTime = -1;
let lastUlidRandom = 0n;
export function canonicalizeKnowledgeScope(scope: KnowledgeScope): KnowledgeScope {
const entriesByLevel = new Map<KnowledgeScopeLevel, string>();
for (const entry of scope) {
const separator = entry.indexOf(':');
const level = entry.slice(0, separator) as KnowledgeScopeLevel;
const id = entry.slice(separator + 1);
if (separator <= 0 || !id || id.includes('\u001f') || SCOPE_ORDER[level] === undefined) {
throw new Error(`Invalid knowledge scope entry: ${entry}`);
}
const existing = entriesByLevel.get(level);
if (existing && existing !== entry) {
throw new Error(`Knowledge scope contains multiple ${level} entries`);
}
entriesByLevel.set(level, entry);
}
if (entriesByLevel.size === 0) {
throw new Error('Knowledge scope cannot be empty');
}
if (entriesByLevel.has('thread') && (!entriesByLevel.has('resource') || !entriesByLevel.has('org'))) {
throw new Error('Thread knowledge scope requires resource and org ancestors');
}
if (entriesByLevel.has('resource') && !entriesByLevel.has('org')) {
throw new Error('Resource knowledge scope requires an org ancestor');
}
const unique = [...new Set(scope)];
unique.sort((a, b) => {
const aLevel = a.slice(0, a.indexOf(':')) as KnowledgeScopeLevel;
const bLevel = b.slice(0, b.indexOf(':')) as KnowledgeScopeLevel;
const aOrder = SCOPE_ORDER[aLevel] ?? Number.MAX_SAFE_INTEGER;View on GitHub (pinned to 75dd419e61)
Solutions
- Deduplicate by level before calling: keep exactly one id per level (the narrowest intended one).
- If two ids at the same level are genuinely different tenants/threads, this is a caller logic bug — pick the correct one or issue separate queries per scope.
- Build scopes via a builder that overwrites per-level entries (last-wins) rather than concatenating arrays.
Example fix
// before
const scope = [`org:${orgA}`, `org:${orgB}`, `resource:${r}`];
// after
const scope = [`org:${orgA}`, `resource:${r}`]; // one entry per level Defensive patterns
Strategy: validation
Validate before calling
function dedupeScopeByLevel(scope: string[]): string[] {
const byLevel = new Map<string, string>();
for (const e of scope) byLevel.set(e.slice(0, e.indexOf(':')), e); // last-wins per level
return [...byLevel.values()];
} Prevention
- Treat KnowledgeScope as 'one entry per level', not an arbitrary list.
- Merge scope sources with a per-level Map, never Array.concat.
- Add a unit test asserting scopes your app builds have unique levels.
When it happens
Trigger: Passing a scope like ['org:a', 'org:b'] or ['thread:t1', 'thread:t2'] to any knowledge API that canonicalizes scope (queryScope, resolveScope, knowledgeScopeKey, expandKnowledgeScope, node writes).
Common situations: Merging scope arrays collected from multiple sources (org config + user config) without deduplicating by level; accidental double-append of the same level with different ids; migrating code that previously treated scope as an arbitrary bag of namespaces.
Related errors
- Invalid knowledge scope entry: ${entry}
- Knowledge scope cannot be empty
- Thread knowledge scope requires resource and org ancestors
- Resource knowledge scope requires an org ancestor
- Cannot expand knowledge scope to ${level}: context has no ${
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/3158453a8be74112.
Report an issue: GitHub.