mastra-ai/mastra · error · Error
Knowledge tools require an active threadId.
Error message
Knowledge tools require an active threadId.
What it means
The observational-memory knowledge tools derive their visibility scope from three coordinates: requestContext.organizationId, agent.resourceId, and agent.threadId. Before any knowledge tool runs, resolveScope builds the scope array [`org:...`, `resource:...`, `thread:...`] and refuses to proceed when the threadId coordinate is missing, because knowledge is always resolved within an active conversation thread. The library throws this to prevent tools from silently operating against an unbounded or ambiguous scope.
Source
Thrown at packages/memory/src/processors/observational-memory/subconscious/knowledge-tools.ts:39
getStore(name: 'knowledge'): Promise<KnowledgeStorage | undefined>;
};
getKnowledgeSemanticIndex(): Promise<KnowledgeSemanticIndexCoordinator>;
};
type KnowledgeToolContext = {
agent?: { threadId?: string; resourceId?: string };
requestContext?: { get(key: string): unknown };
};
function resolveScope(context: KnowledgeToolContext | undefined): KnowledgeScope {
const organizationId = context?.requestContext?.get('organizationId');
const resourceId = resolveKnowledgeResourceId(context?.requestContext, context?.agent?.resourceId);
const threadId = context?.agent?.threadId;
if (typeof organizationId !== 'string' || !organizationId.trim()) {
throw new Error('Knowledge tools require requestContext.organizationId.');
}
if (!resourceId) throw new Error('Knowledge tools require an active resourceId.');
if (!threadId) throw new Error('Knowledge tools require an active threadId.');
return [`org:${organizationId}`, `resource:${resourceId}`, `thread:${threadId}`];
}
async function getKnowledgeStore(memory: KnowledgeToolsMemory): Promise<KnowledgeStorage> {
const store = await memory.storage.getStore('knowledge');
if (!store) throw new Error('Knowledge tools require a configured knowledge storage domain.');
return store;
}
function normalizeLimit(limit: number | undefined): number {
return Math.min(Math.max(limit ?? DEFAULT_LIMIT, 1), MAX_LIMIT);
}
function serializeRecord(record: KnowledgeRecord) {
return {
id: record.id,
text: record.text,
scope: record.scope,View on GitHub (pinned to 75dd419e61)
Solutions
- Run the agent through the normal Mastra memory flow so a thread is created and context.agent.threadId is populated before tools execute.
- If calling tools manually, pass a context object with agent: { threadId: '<existing-thread-id>', resourceId: '<resource-id>' }.
- Create a thread first (via memory storage or agent.memory APIs) and use its ID.
- Verify requestContext also supplies organizationId and resourceId, since those are checked first and their absence masks later checks.
Example fix
// before
const tools = createKnowledgeTools(memory);
await tools.knowledge_read.execute({ id: 'node-1' }, {} as any);
// after
await tools.knowledge_read.execute({ id: 'node-1' }, {
agent: { threadId: 'thread_123', resourceId: 'user_42' },
requestContext: { get: (k) => (k === 'organizationId' ? 'org_1' : undefined) },
} as any); Defensive patterns
Strategy: validation
Validate before calling
const ctx = context as { agent?: { threadId?: string; resourceId?: string }; requestContext?: { get(k: string): unknown } };
if (!ctx?.agent?.threadId) {
throw new Error('Refusing to invoke knowledge tools: no active threadId.');
} Type guard
function hasThreadContext(c: unknown): c is { agent: { threadId: string; resourceId: string }; requestContext: { get(k: string): unknown } } {
const a = (c as any)?.agent;
return typeof a?.threadId === 'string' && a.threadId.trim() !== '' && typeof a?.resourceId === 'string';
} Try / catch
try {
return await tools.knowledge_read.execute(args, ctx);
} catch (e) {
if (e instanceof Error && e.message.includes('active threadId')) {
return { error: 'no-active-thread', hint: 'Run inside a memory-backed agent thread.' };
}
throw e;
} Prevention
- Always invoke knowledge tools inside a memory-backed agent run so threadId is set.
- When testing manually, stub agent: { threadId, resourceId } in the context.
- Create the thread before wiring knowledge tools.
- Assert all three scope inputs (organizationId, resourceId, threadId) in a pre-flight helper.
When it happens
Trigger: Invoking any knowledge tool (knowledge_read, knowledge_search, etc.) via createKnowledgeTools when context.agent.threadId is undefined — e.g. calling the tool outside a memory-backed agent run, or in a unit test harness that stubs context without a threadId.
Common situations: Developers testing knowledge tools in isolation with a hand-rolled context object that omits threadId; running the curator/learner agent outside a normal Mastra agent loop; calling tools during startup or background jobs where no thread has been created yet.
Related errors
- Knowledge tools require a configured knowledge storage domai
- Knowledge tools require requestContext.organizationId.
- Knowledge tools require an active resourceId.
- knowledge_read requires id or name.
- Knowledge write tools require a configured knowledge storage
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/16c1c72258382262.
Report an issue: GitHub.