{"record":{"id":"dcfce10e3d831598","repo":"nodejs/node","slug":"max-redirects","errorCode":null,"errorMessage":"max redirects","messagePattern":"max redirects","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"deps/undici/src/lib/handler/redirect-handler.js","lineNumber":52,"sourceCode":"    this.opts.body = util.wrapRequestBody(this.opts.body)\n    this.stripHeadersOnRedirect = normalizeStripHeaders(stripHeadersOnRedirect, 'stripHeadersOnRedirect')\n    this.stripHeadersOnCrossOriginRedirect = normalizeStripHeaders(stripHeadersOnCrossOriginRedirect, 'stripHeadersOnCrossOriginRedirect')\n    this.maxRedirections = maxRedirections\n    this.handler = handler\n    this.history = []\n  }\n\n  onRequestStart (controller, context) {\n    this.handler.onRequestStart?.(controller, { ...context, history: this.history })\n  }\n\n  onRequestUpgrade (controller, statusCode, headers, socket) {\n    this.handler.onRequestUpgrade?.(controller, statusCode, headers, socket)\n  }\n\n  onResponseStart (controller, statusCode, headers, statusMessage) {\n    if (this.opts.throwOnMaxRedirect && this.history.length >= this.maxRedirections) {\n      throw new Error('max redirects')\n    }\n\n    let removeContentHeaders = statusCode === 303\n\n    // https://tools.ietf.org/html/rfc7231#section-6.4.2\n    // https://fetch.spec.whatwg.org/#http-redirect-fetch\n    // In case of HTTP 301 or 302 with POST, change the method to GET\n    // QUERY is safe (RFC 10008) and should not change method like GET.\n    if ((statusCode === 301 || statusCode === 302) && this.opts.method === 'POST') {\n      this.opts.method = 'GET'\n      if (util.isStream(this.opts.body)) {\n        util.destroy(this.opts.body.on('error', noop))\n      }\n      this.opts.body = null\n      removeContentHeaders = true\n    }\n\n    // https://tools.ietf.org/html/rfc7231#section-6.4.4","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/undici/src/lib/handler/redirect-handler.js#L34-L70","documentation":"A plain Error (not InvalidArgumentError) thrown from RedirectHandler.onResponseStart when opts.throwOnMaxRedirect is true and the number of redirects already followed (this.history.length) has reached maxRedirections. This is the intended, opted-in behavior: the caller asked to be notified when the redirect cap is hit rather than receiving the redirect response silently.","triggerScenarios":"Setting throwOnMaxRedirect: true together with a maxRedirections value (including 0) and then hitting a redirect chain whose length meets or exceeds the cap. With maxRedirections: 0 even the first 3xx response triggers it.","commonSituations":"Tight redirect budgets set to catch redirect loops; misconfigured maxRedirections that is too low for the target site's normal redirect chain; legitimately long login/SSO redirect flows.","solutions":["Increase maxRedirections to a value that comfortably covers the expected redirect chain (e.g. 5-10).","If you would rather get the final 3xx response than an error, remove throwOnMaxRedirect (or set it to false).","Wrap the request in try/catch and treat this error as a signal to retry against the last Location with a fresh request."],"exampleFix":"// before\nconst agent = new Agent({ maxRedirections: 1, throwOnMaxRedirect: true })\n\n// after\nconst agent = new Agent({ maxRedirections: 5 })\n// or, opt out of throwing and inspect the 3xx response yourself:\n// const agent = new Agent({ maxRedirections: 1 })","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await agent.request({ path, method: 'GET', maxRedirections, throwOnMaxRedirect: true })\n} catch (e) {\n  if (e.message === 'max redirects') {\n    // bump budget or follow the last Location manually\n  } else throw e\n}","preventionTips":["Size maxRedirections to the longest legitimate redirect chain for the target.","Only set throwOnMaxRedirect when you genuinely want to abort on cap.","Log the redirect history to diagnose chains that grow over time."],"tags":["undici","http","redirect","runtime-condition"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}