SubtitleEdit/subtitleedit · error · LensError

Lens returned status code {(int)response.StatusCode}

Error message

Lens returned status code {(int)response.StatusCode}

What it means

A custom LensError thrown when the reverse-engineered Google Lens HTTP endpoint answers with a non-2xx status. It carries the numeric status code, response headers, and the body so callers can branch on 429 (rate limit), 4xx, or redirect/CAPTCHA challenges. Because this is an unofficial scrape of Lens, Google can change or break it at any time.

Source

Thrown at src/ui/Logic/Ocr/GoogleLens/LensCore.cs:332

        foreach (var kvp in headers)
        {
            if (kvp.Key.ToLower() != "content-type")
            {
                request.Headers.TryAddWithoutValidation(kvp.Key, kvp.Value);
            }
        }

        var response = await _fetch!(request);

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

        if (!response.IsSuccessStatusCode)
        {
            var errorBody = await response.Content.ReadAsStringAsync();
            throw new LensError($"Lens returned status code {(int)response.StatusCode}", (int)response.StatusCode, response.Headers, errorBody);
        }

        var responseBytes = await response.Content.ReadAsByteArrayAsync();
        return LensProtoResponse.Deserialize(responseBytes);
    }

    public async Task<LensResult> ScanByData(byte[] uint8Array, string mime, int[] originalDimensions, string twoLetterLanguageCode)
    {
        if (!Constants.SUPPORTED_MIMES.Contains(mime) && mime != "image/gif")
        {
            Console.WriteLine($"MIME type {mime} might not be directly supported by the proto API, conversion recommended.");
        }

        var actualDimensions = Helper.ImageDimensionsFromData(uint8Array);

        var serializedRequest = CreateLensProtoRequest(uint8Array, actualDimensions.Width, actualDimensions.Height);
        var serverResponse = await SendProtoRequest(serializedRequest, twoLetterLanguageCode);

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Inspect LensError.StatusCode and Body: 429 -> back off and retry with jitter honoring Retry-After; 3xx/200-HTML -> re-run cookie seeding before retrying.
  2. Seed/warm cookies before the first ScanByData call so the session looks legitimate.
  3. Throttle concurrent Lens scans to avoid rate limiting.
  4. Check the upstream library for an updated Lens protobuf/endpoint if a 400/404 persists.
  5. Retry once on transient 5xx with exponential backoff.

Example fix

// before
var result = await lens.ScanByData(buffer, mime, dims, lang);

// after
try { return await lens.ScanByData(buffer, mime, dims, lang); }
catch (LensError ex) when (ex.StatusCode == 429)
{
    var delay = ex.Headers?.RetryAfter?.Delta ?? TimeSpan.FromSeconds(5);
    await Task.Delay(delay);
    return await lens.ScanByData(buffer, mime, dims, lang);
}
Defensive patterns

Strategy: retry

Try / catch

try { return await lens.ScanByData(buffer, mime, dims, lang); }
catch (LensError ex)
{
    if (ex.StatusCode == 429)
    {
        var delay = ex.Headers?.RetryAfter?.Delta ?? TimeSpan.FromSeconds(5);
        await Task.Delay(delay);
        return await lens.ScanByData(buffer, mime, dims, lang);
    }
    if (ex.StatusCode >= 500) { await Task.Delay(Backoff(attempt)); return await lens.ScanByData(buffer, mime, dims, lang); }
    throw;
}

Prevention

When it happens

Trigger: _fetch returns a response with !IsSuccessStatusCode. Typical statuses: 401/403 (stale or missing cookies), 429 (rate limiting), 3xx or 200-with-HTML (CAPTCHA/consent redirect), 400/404 (Google changed the endpoint or rejected the protobuf payload), 5xx (transient Google outage).

Common situations: First run without warming cookies, batch OCR tripping rate limits, IP behind a shared NAT/VPN that Google flags, or a Google anti-bot rollout that invalidates the request shape.

Related errors


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