{"record":{"id":"02ffb0775c0c7353","repo":"mastra-ai/mastra","slug":"thread-not-found-on-gateway","errorCode":null,"errorMessage":"Thread not found on gateway","messagePattern":"Thread not found on gateway","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"error","filePath":"packages/server/src/server/handlers/memory.ts","lineNumber":1568,"sourceCode":"      const agent = await getAgentFromContext({ mastra, agentId, requestContext });\n      if (agent && (await isGatewayAgentAsync(agent))) {\n        const gwClient = getGatewayClient();\n        if (gwClient) {\n          // Validate ownership before deleting\n          const existing = await gwClient.getThread(effectiveThreadId!);\n          if (existing) {\n            await enforceThreadAccess({\n              mastra,\n              requestContext,\n              threadId: effectiveThreadId!,\n              thread: toLocalThread(existing.thread),\n              effectiveResourceId,\n              permission: MastraFGAPermissions.MEMORY_DELETE,\n            });\n          }\n          const deleteResult = await gwClient.deleteThread(effectiveThreadId!);\n          if (!deleteResult.ok) {\n            throw new HTTPException(404, { message: 'Thread not found on gateway' });\n          }\n          return { result: 'Thread deleted' };\n        }\n      }\n\n      const memory = await getMemoryFromContext({ mastra, agentId, requestContext });\n      if (!memory) {\n        throw new HTTPException(400, { message: 'Memory is not initialized' });\n      }\n\n      const thread = await memory.getThreadById({ threadId: effectiveThreadId! });\n      if (!thread) {\n        throw new HTTPException(404, { message: 'Thread not found' });\n      }\n      await enforceThreadAccess({\n        mastra,\n        requestContext,\n        threadId: effectiveThreadId!,","sourceCodeStart":1550,"sourceCodeEnd":1586,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/memory.ts#L1550-L1586","documentation":"DELETE /memory/threads/:threadId, on the gateway-agent path, calls `gwClient.deleteThread`. If the gateway response is not ok, the handler throws HTTP 404 'Thread not found on gateway' — specifically indicating the delete failed at the gateway because no such thread exists there (as opposed to local storage).","triggerScenarios":"DELETE /api/memory/threads/:threadId with ?agentId= of a gateway-backed agent where the threadId was never created on the gateway or was already deleted; also non-ok gateway responses surfaced as this 404.","commonSituations":"Threads created locally before gateway migration being deleted through the gateway path; double-delete (idempotency gaps) from retrying UI actions; gateway pointed at a different environment than where the thread exists.","solutions":["Treat 404 as success for idempotent deletes: catch it and consider the thread already gone.","Verify the thread exists on the gateway first (gwClient/GET thread) if you need to distinguish missing vs failed.","For pre-gateway local threads, delete via a non-gateway agent/context or migrate the thread to the gateway.","Check gateway client configuration to ensure you target the environment where the thread lives."],"exampleFix":"// before\nawait client.deleteThread(threadId); // throws 404 if already gone\n// after\ntry {\n  await client.deleteThread(threadId);\n} catch (e) {\n  if (e.status !== 404) throw e; // idempotent delete\n}","handlingStrategy":"fallback","validationCode":"const existing = await gwClient.getThread(threadId);\nif (!existing) {\n  return { alreadyDeleted: true }; // nothing to delete on gateway\n}","typeGuard":null,"tryCatchPattern":"try {\n  await client.deleteThread(threadId);\n} catch (e) {\n  if (isHttpError(e) && e.status === 404 && /gateway/.test(e.message)) {\n    // treat as already-deleted (idempotent); optionally fall back to local deletion\n  } else throw e;\n}","preventionTips":["Make deletes idempotent: a 404 means the goal state is already reached.","After gateway migration, delete legacy local threads through the local path or migrate them first.","Verify gateway environment/project config before destructive operations.","Guard UI delete buttons against double-submission to avoid confusing 404s."],"tags":["http-404","gateway","delete","not-found"],"backgroundTag":"thread-not-found","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}