mastra-ai/mastra · error · HTTPException
threadId is required
Error message
threadId is required
What it means
The abort endpoint needs a threadId to know which agent thread's stream to abort. After resolving effective values (including requestContext overrides), a missing threadId throws HTTP 400. resourceId is optional here — it only triggers extra ownership validation when present.
Source
Thrown at packages/server/src/server/handlers/agents.ts:2167
summary: 'Abort active agent thread run',
description: 'Aborts the currently active stream run for a memory thread without changing thread subscriptions',
tags: ['Agents', 'Streaming'],
requiresAuth: true,
requiresPermission: 'agents:execute',
handler: async ({ mastra, agentId, resourceId, threadId, requestContext: serverRequestContext }) => {
try {
const agent = await getAgentFromSystem({ mastra, agentId, requestContext: serverRequestContext });
if (typeof (agent as { abortThreadStream?: unknown }).abortThreadStream !== 'function') {
throw new HTTPException(501, {
message: 'agent thread aborts are not supported by this Mastra core version',
});
}
const effectiveResourceId = getEffectiveResourceId(serverRequestContext, resourceId);
const effectiveThreadId = getEffectiveThreadId(serverRequestContext, threadId);
if (!effectiveThreadId) {
throw new HTTPException(400, { message: 'threadId is required' });
}
if (effectiveResourceId) {
const memory = await agent.getMemory({ requestContext: serverRequestContext });
if (memory) {
const thread = await memory.getThreadById({ threadId: effectiveThreadId });
await validateThreadOwnership(thread, effectiveResourceId);
}
}
const aborted = await agent.abortThreadStream({ resourceId: effectiveResourceId, threadId: effectiveThreadId });
return { aborted };
} catch (error) {
return handleError(error, 'error aborting agent thread');
}
},
});
View on GitHub (pinned to 75dd419e61)
Solutions
- Pass threadId in the request
- Ensure the thread ID from stream metadata (e.g. stream.threadId) is captured and reused
- Check requestContext overrides if you rely on context to inject threadId
Example fix
// before
await client.getAgent('a').abortThread({ resourceId: 'u1' });
// after
await client.getAgent('a').abortThread({ resourceId: 'u1', threadId: 'thread-42' }); Defensive patterns
Strategy: validation
Validate before calling
function assertThreadId(p: { threadId?: string | null }): asserts p is { threadId: string } {
if (!p.threadId) throw new Error('threadId is required');
} Type guard
function hasThreadId(p: { threadId?: string | null }): p is typeof p & { threadId: string } {
return typeof p.threadId === 'string' && p.threadId.length > 0;
} Try / catch
try {
await abortThread(params);
} catch (e) {
if (e?.status === 400 && e.message === 'threadId is required') {
console.error('Persist the threadId from the stream before aborting');
}
throw e;
} Prevention
- Store threadId from stream start events immediately
- Use one consistent field name (threadId) across client and API calls
- Disable abort actions in the UI until a threadId exists in state
When it happens
Trigger: Calling the thread abort route without threadId in params/body and without a requestContext override supplying it.
Common situations: Client aborting a run-level stream but passing no threadId; typo'd field name (thread_id vs threadId); thread created client-side but its ID never persisted/sent.
Understand the failure class
Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.
Related errors
- resourceId and threadId are required when runId is not provi
- Run id is required
- Agent ID is required
- Cannot delete the active version. Activate a different versi
- ${error.message}
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/f798d6d4ea194216.
Report an issue: GitHub.