{"record":{"id":"e5c18010c6907654","repo":"mastra-ai/mastra","slug":"mcp-client-redirect-missing-location","errorCode":"MCP_CLIENT_REDIRECT_MISSING_LOCATION","errorMessage":"Received a ${response.status} redirect with no Location header from \"${currentUrl.host}\" while following redirects under the allowedHosts policy.","messagePattern":"Received a (.+?) redirect with no Location header from \"(.+?)\" while following redirects under the allowedHosts policy\\.","errorType":"error_code","errorClass":"MastraError","httpStatus":null,"severity":"error","filePath":"packages/mcp/src/client/url-policy.ts","lineNumber":205,"sourceCode":"  fetchImpl: (url: string | URL, init?: RequestInit) => Promise<Response>,\n  url: string | URL,\n  init: RequestInit | undefined,\n  allowedHosts: readonly string[],\n): Promise<Response> {\n  let currentUrl = assertHostAllowed(url, allowedHosts);\n  let method = init?.method ?? 'GET';\n  let body = init?.body;\n  const headers = new Headers(init?.headers);\n\n  for (let redirectsFollowed = 0; ; redirectsFollowed++) {\n    const response = await fetchImpl(currentUrl, { ...init, method, body, headers, redirect: 'manual' });\n    if (!REDIRECT_STATUS_CODES.has(response.status)) {\n      return response;\n    }\n\n    const location = response.headers.get('location');\n    if (!location) {\n      throw new MastraError({\n        id: 'MCP_CLIENT_REDIRECT_MISSING_LOCATION',\n        domain: ErrorDomain.MCP,\n        category: ErrorCategory.THIRD_PARTY,\n        text: `Received a ${response.status} redirect with no Location header from \"${currentUrl.host}\" while following redirects under the allowedHosts policy.`,\n      });\n    }\n    if (redirectsFollowed >= MAX_REDIRECT_HOPS) {\n      throw new MastraError({\n        id: 'MCP_CLIENT_TOO_MANY_REDIRECTS',\n        domain: ErrorDomain.MCP,\n        category: ErrorCategory.THIRD_PARTY,\n        // Interpolate only the host, not the full URL: a URL's path/query could\n        // contain substrings (e.g. \"sessionId\") that isReconnectableMCPError\n        // matches, which would misclassify this terminal failure as transient.\n        text: `Exceeded the maximum of ${MAX_REDIRECT_HOPS} redirect hops while requesting host \"${currentUrl.host}\" under the allowedHosts policy.`,\n      });\n    }\n","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/mcp/src/client/url-policy.ts#L187-L223","documentation":"When fetchFollowingAllowedRedirects (the allowedHosts-aware fetch used by the MCP client) receives a 3xx redirect response, it requires a Location header to know where to follow. If the server sends a redirect status with no Location header, this MastraError (MCP_CLIENT_REDIRECT_MISSING_LOCATION, THIRD_PARTY) is thrown.","triggerScenarios":"A remote MCP server (or intermediary proxy) returns 301/302/303/307/308 without a Location header while the client uses an allowedHosts URL policy.","commonSituations":"Misconfigured reverse proxies or gateways behind the MCP server; broken load balancer health redirects; corporate proxies that strip Location headers.","solutions":["Inspect the raw response with curl -v and fix the server/proxy to include a Location header on redirects","Bypass the broken intermediary or correct its redirect configuration","Point the client directly at the final destination URL so no redirect occurs","If the redirect is legitimate, verify headers are not being stripped by middleware"],"exampleFix":"// before (server side, bad)\nres.writeHead(302); res.end();\n// after\nres.writeHead(302, { Location: 'https://target.example.com/mcp' }); res.end();","handlingStrategy":"retry","validationCode":"const res = await fetch(url, { method: 'HEAD', redirect: 'manual' });\nif (REDIRECT_STATUS_CODES.has(res.status) && !res.headers.get('location')) {\n  throw new Error(`Upstream ${res.status} at ${url.host} lacks Location header; fix server/proxy before MCP calls`);\n}","typeGuard":"null","tryCatchPattern":"try {\n  await client.tools();\n} catch (e) {\n  if (e instanceof MastraError && e.id === 'MCP_CLIENT_REDIRECT_MISSING_LOCATION') {\n    console.error('Intermediary sent a redirect without Location; bypass proxy or fix gateway config');\n  } else throw e;\n}","preventionTips":["Test MCP endpoints with curl -IL to confirm redirects carry Location","Avoid intermediary proxies that emit bare 3xx responses","Point the client directly at the final URL when redirects are known"],"tags":["mcp","redirect","network","url-policy"],"backgroundTag":"redirect-loop","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}