{"record":{"id":"a1a83c0ad04de182","repo":"deepseek-ai/deepseek-harness","slug":"web-redirect-blocked","errorCode":"WEB_REDIRECT_BLOCKED","errorMessage":"exceeded the maximum of ${this.limits.maxRedirects} redirects","messagePattern":"exceeded the maximum of (.+?) redirects","errorType":"error_code","errorClass":"WebError","httpStatus":null,"severity":"error","filePath":"packages/web/web-fetch-http/src/provider.ts","lineNumber":67,"sourceCode":"    // One signal stops both the request and body read. The deadline's TimeoutReason later\n    // distinguishes this provider's timeout from caller or outer-deadline cancellation.\n    using d = deadline(signal, this.limits.timeoutMs, 'WEB_FETCH_TIMEOUT')\n    return await this.followAndRead(request.url, d.signal)\n  }\n\n  /** Follow same-origin redirects up to the hop cap, then read the final response. */\n  private async followAndRead(initialUrl: string, signal: AbortSignal): Promise<WebFetchResult> {\n    let currentUrl = validateFetchUrl(initialUrl, this.limits.maxUrlLength)\n    let redirectsFollowed = 0\n\n    for (;;) {\n      const response = await this.requestOnce(currentUrl, signal)\n\n      if (isRedirectStatus(response.status)) {\n        // Enforce the redirect budget before resolving or validating the next hop.\n        if (redirectsFollowed >= this.limits.maxRedirects) {\n          await response.body?.cancel()\n          throw new WebError(`exceeded the maximum of ${this.limits.maxRedirects} redirects`, 'WEB_REDIRECT_BLOCKED')\n        }\n        const location = response.headers.get('location')\n        if (location === null) {\n          // A redirect status with no Location is not a usable resource. Cancel\n          // the (possibly streaming) body before throwing so no socket leaks.\n          await response.body?.cancel()\n          throw new WebError(`redirect response (HTTP ${response.status}) without a Location header`, 'WEB_PROVIDER_ERROR')\n        }\n        const target = resolveRedirect(location, currentUrl)\n        // Re-validate the target against the same transport hygiene a direct request gets: a\n        // redirect must not be a back door to a credentialed, non-http(s), or over-long URL\n        // that validateFetchUrl would reject.\n        let validatedTarget: URL\n        try {\n          validatedTarget = validateFetchUrl(target.toString(), this.limits.maxUrlLength)\n          if (!isSameOrigin(validatedTarget, currentUrl)) {\n            throw new WebError(\n              `cross-origin redirect to ${validatedTarget.origin} is not followed automatically; retry against that URL directly`,","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/deepseek-ai/deepseek-harness/blob/b150a551b8d465e31e418e1b2eaf5e79bbb7d28e/packages/web/web-fetch-http/src/provider.ts#L49-L85","documentation":"Error \"exceeded the maximum of ${this.limits.maxRedirects} redirects\" thrown in deepseek-ai/deepseek-harness.","triggerScenarios":"Thrown at packages/web/web-fetch-http/src/provider.ts:67 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Fix the redirect loop on the server, or raise maxRedirects if the chain is legitimate."],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"b150a551b8d465e31e418e1b2eaf5e79bbb7d28e","analyzedAt":"2026-08-24T18:12:29.105Z","schemaVersion":2},"datasetVersion":"2026-08-24T22:17:12.610Z"}