SubtitleEdit/subtitleedit · error · CoreError

Lens returned a non-200 status code

Error message

Lens returned a non-200 status code

What it means

Thrown by Core.FetchAsync when, after exhausting the 302/consent handling, the final response status is anything other than 200 OK. Wrapped in CoreError with the numeric status, headers, and raw text so the caller can diagnose (e.g. 400 bad request, 429 rate limit, 500 server error, 403 blocked).

Source

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

                saveConsentRequest.Headers.Add(kvp.Key, kvp.Value);
            }

            var saveConsentResponse = await _fetch(saveConsentRequest);

            if (saveConsentResponse.StatusCode == System.Net.HttpStatusCode.SeeOther)
            {
                if (saveConsentResponse.Headers.TryGetValues("set-cookie", out var consentCookies))
                {
                    SetCookies(consentCookies);
                }
                await Task.Delay(500);
                return await FetchAsync(formdata, originalDimensions, true);
            }
        }

        if (response.StatusCode != System.Net.HttpStatusCode.OK)
        {
            throw new CoreError("Lens returned a non-200 status code", (int)response.StatusCode, response.Headers, text);
        }

        try
        {
            var afData = GetAFData(responseBody);
            return ParseResult(afData!, originalDimensions);
        }
        catch (Exception e)
        {
            throw new CoreError($"Could not parse response: {e.Message}", (int)response.StatusCode, response.Headers, text);
        }
    }
    
    public async Task<List<string>> ScanByData(byte[] uint8, string mime, int[] originalDimensions)
    {
        if (!Constants.SUPPORTED_MIMES.Contains(mime))
        {
            throw new Exception("File type not supported");

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Inspect CoreError.StatusCode: back off on 429, switch engine on 403, fix payload on 400.
  2. Exponential backoff + retry for 5xx and 429 responses.
  3. Rotate User-Agent / proxy if 403 persists.
  4. Refresh cookies by re-running the consent handshake from a clean session.

Example fix

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

// after
try { var result = await core.FetchAsync(formdata, dims); }
catch (CoreError ex) { if (ex.StatusCode == 429) await Task.Delay(5000); else throw; }
Defensive patterns

Strategy: retry

Validate before calling

// Cannot prevent a server-side non-200, but you can pre-check connectivity:
if (await HttpClientFactoryWithProxy.CreateHttpClientWithProxy().GetAsync(HeaderData.Config["endpoint"].ToString()) is { } probe && !probe.IsSuccessStatusCode) { /* degrading */ }

Try / catch

try { var r = await core.FetchAsync(formdata, dims); }
catch (CoreError ex)
{
    if (ex.StatusCode == 429) await Task.Delay(5000);
    else if (ex.StatusCode >= 500) await Task.Delay(1000);
    else throw;
}

Prevention

When it happens

Trigger: Lens returns 429 (too many requests), 403 (blocked/forbidden), 400 (malformed multipart), 500/502/503 (server/edge fault), or any non-200/non-302 status after the consent flow completes.

Common situations: Rate limiting from too many OCR calls; Google blocking the User-Agent/IP; a malformed multipart body; upstream outage; expired/invalid cookies yielding 403.

Related errors


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