SubtitleEdit/subtitleedit · error · CoreError

Lens returned a 302 status code twice

Error message

Lens returned a 302 status code twice

What it means

Thrown by Core.FetchAsync when Google Lens responds with HTTP 302 (Found) on the retry pass (secondTry == true). The first 302 triggers a consent-screen handshake (posting to consent.google.com/save and retrying); a second consecutive 302 means the consent flow did not establish a usable session, so the client gives up rather than loop indefinitely. Wrapped in CoreError carrying status, headers, and response text.

Source

Thrown at src/ui/Logic/Ocr/GoogleLens/Core.cs:162

            responseBytes = Helper.DecompressDeflate(responseBytes);
        }
        if (response.Content.Headers.ContentEncoding.Contains("br"))
        {
            responseBytes = Helper.DecompressBrotli(responseBytes);
        }
        
        var responseBody = Encoding.UTF8.GetString(responseBytes);

        if (response.Headers.TryGetValues("set-cookie", out var setCookieValues))
        {
            SetCookies(setCookieValues);
        }

        if (response.StatusCode == System.Net.HttpStatusCode.Found)
        {
            if (secondTry)
            {
                throw new CoreError("Lens returned a 302 status code twice", (int)response.StatusCode, response.Headers, text);
            }

            var consentHeaders = HeaderData.GenerateHeaders();
            consentHeaders["Content-Type"] = "application/x-www-form-urlencoded";
            consentHeaders["Referer"] = "https://consent.google.com/";
            consentHeaders["Origin"] = "https://consent.google.com";

            GenerateCookieHeader(consentHeaders);

            var location = response.Headers.Location;
            if (location == null)
            {
                throw new Exception("Location header not found");
            }

            var redirectLink = new Uri(location.ToString());
            var params2 = new Dictionary<string, string>
            {

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Ensure the HTTP client (HttpClientFactoryWithProxy.CreateHttpClientWithProxy) honors cookies and redirects are not auto-followed.
  2. Update the consent parameters / endpoint tokens if Google changed them.
  3. Retry the whole OCR call after a delay, or fall back to a different OCR engine.
  4. Inspect the CoreError response text and headers to see where the redirect points.

Example fix

// before
var result = await core.FetchAsync(formdata, dims);

// after
try { var result = await core.FetchAsync(formdata, dims); }
catch (CoreError ex) when (ex.Message.Contains("302 twice")) { return await FallbackOcrAsync(image); }
Defensive patterns

Strategy: retry

Validate before calling

// Cannot fully prevent a server-side 302, but ensure cookies are enabled:
var client = HttpClientFactoryWithProxy.CreateHttpClientWithProxy(); // verify it uses a CookieContainer
// Ensure HttpClient does not auto-follow redirects (so the consent flow can run).

Try / catch

try { var r = await core.FetchAsync(formdata, dims); }
catch (CoreError ex) when (ex.Message.Contains("302 status code twice"))
{ await Task.Delay(2000); return await RetryOrFallbackAsync(); }

Prevention

When it happens

Trigger: Repeated 302 redirects from Lens after the consent handshake — e.g. cookies were not accepted, the consent POST itself redirected again, or Google changed the consent flow. Network/proxy environments that strip Set-Cookie headers also cause this.

Common situations: A proxy or corporate firewall dropping Set-Cookie; an outdated hardcoded consent 'bl' token (boq_identityfrontenduiserver_20240129.02_p0) that Google rotated; regional consent requirements the handshake does not satisfy; rate limiting returning redirects.

Related errors


AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13). Data as JSON: /api/errors/5dde74543784aeb1. Report an issue: GitHub.