{"record":{"id":"246a8fe838e61da9","repo":"SubtitleEdit/subtitleedit","slug":"location-header-not-found","errorCode":null,"errorMessage":"Location header not found","messagePattern":"Location header not found","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/ui/Logic/Ocr/GoogleLens/Core.cs","lineNumber":175,"sourceCode":"\n        if (response.StatusCode == System.Net.HttpStatusCode.Found)\n        {\n            if (secondTry)\n            {\n                throw new CoreError(\"Lens returned a 302 status code twice\", (int)response.StatusCode, response.Headers, text);\n            }\n\n            var consentHeaders = HeaderData.GenerateHeaders();\n            consentHeaders[\"Content-Type\"] = \"application/x-www-form-urlencoded\";\n            consentHeaders[\"Referer\"] = \"https://consent.google.com/\";\n            consentHeaders[\"Origin\"] = \"https://consent.google.com\";\n\n            GenerateCookieHeader(consentHeaders);\n\n            var location = response.Headers.Location;\n            if (location == null)\n            {\n                throw new Exception(\"Location header not found\");\n            }\n\n            var redirectLink = new Uri(location.ToString());\n            var params2 = new Dictionary<string, string>\n            {\n                { \"x\", \"6\" },\n                { \"set_eom\", \"true\" },\n                { \"bl\", \"boq_identityfrontenduiserver_20240129.02_p0\" },\n                { \"app\", \"0\" }\n            };\n\n            await Task.Delay(500);\n\n            var saveConsentRequest = new HttpRequestMessage(HttpMethod.Post, \"https://consent.google.com/save\")\n            {\n                Content = new FormUrlEncodedContent(params2)\n            };\n","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Logic/Ocr/GoogleLens/Core.cs#L157-L193","documentation":"Thrown by Core.FetchAsync inside the 302 handling branch when response.Headers.Location is null. The consent redirect logic needs the Location URI to follow the redirect; if Google returned a 302 without a Location header (malformed response or intermediate proxy), the handshake cannot proceed and a generic Exception is raised.","triggerScenarios":"A 302 response missing the Location header — e.g. a transparent proxy rewrote the redirect, an upstream returned a 302 with an empty body and no Location, or Google's edge returned an error page with status 302.","commonSituations":"Corporate proxies that strip or alter Location; a transient Google edge error; a malformed intermediate response from a CDN.","solutions":["Catch this and treat the Lens call as failed, falling back to another OCR source.","Inspect response.Headers (available via the CoreError path if rethrown) for alternate redirect hints.","Retry the request once; transient missing headers sometimes resolve.","Bypass the proxy for lens.googleapis.com / consent.google.com if possible."],"exampleFix":"// before\nvar result = await core.FetchAsync(formdata, dims);\n\n// after\ntry { var result = await core.FetchAsync(formdata, dims); }\ncatch (Exception ex) when (ex.Message == \"Location header not found\") { await Task.Delay(1000); return await RetryOcrAsync(); }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { var r = await core.FetchAsync(formdata, dims); }\ncatch (Exception ex) when (ex.Message == \"Location header not found\")\n{ await Task.Delay(1000); return await RetryOrFallbackAsync(); }","preventionTips":["Inspect the response headers (via CoreError if rethrown) to find alternate redirect hints.","Retry once; missing Location is often transient or proxy-induced.","Bypass proxies that alter redirect headers for Google domains.","Fall back to an alternate OCR engine on persistent failure."],"tags":["google-lens","ocr","network","http","redirect","proxy"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}