{"record":{"id":"54d3e5fac736626f","repo":"SubtitleEdit/subtitleedit","slug":"could-not-get-access-token-via-tokenendpoint-r","errorCode":null,"errorMessage":"Could not get access token via {tokenEndpoint}: {result}","messagePattern":"Could not get access token via (.+?): (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/libuilogic/AutoTranslate/MicrosoftTranslator.cs","lineNumber":157,"sourceCode":"            }\n\n            return _httpClient;\n        }\n\n        private static string GetAccessToken(string apiKey, string tokenEndpoint)\n        {\n            return Task.Run(async () =>\n            {\n                using (var httpClient = DownloaderFactory.MakeHttpClient())\n                {\n                    httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(\"application/json\"));\n                    httpClient.DefaultRequestHeaders.TryAddWithoutValidation(SecurityHeaderName, apiKey);\n                    var response = await httpClient.PostAsync(tokenEndpoint, new StringContent(string.Empty)).ConfigureAwait(false);\n                    var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false);\n                    if (!response.IsSuccessStatusCode)\n                    {\n                        SeLogger.Error($\"{StaticName}: Error getting access token via {tokenEndpoint}: status code={response.StatusCode} {result}\");\n                        throw new Exception($\"Could not get access token via {tokenEndpoint}: {result}\");\n                    }\n\n                    return result;\n                }\n            }).GetAwaiter().GetResult();\n        }\n\n        private static List<TranslationPair> GetTranslationPairs()\n        {\n            if (_translationPairs != null)\n            {\n                return _translationPairs;\n            }\n\n            return Task.Run(async () =>\n            {\n                using (var httpClient = DownloaderFactory.MakeHttpClient())\n                {","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/libuilogic/AutoTranslate/MicrosoftTranslator.cs#L139-L175","documentation":"Thrown by MicrosoftTranslator.GetAccessToken when the POST to the Azure token endpoint (issueToken) returns a non-success status. The endpoint URL and the response body are included. This is the root cause wrapped by error 52 ('Can't get Access Token'). It is logged via SeLogger before throwing.","triggerScenarios":"GetAccessToken POSTs an empty body to the configured token endpoint with Ocp-Apim-Subscription-Key = apiKey; response.IsSuccessStatusCode is false. Typical statuses: 401 (wrong key), 403 (key for wrong resource/region), 404 (wrong endpoint URL).","commonSituations":"Wrong token endpoint URL (copy-paste error, missing /sts/v1.0/issueToken); key from a different region; key revoked or rotated; endpoint behind a firewall that rewrites responses; free-tier key exhausted.","solutions":["Copy the exact token endpoint from the Azure resource's 'Keys and Endpoint' / 'Resource Management' blade.","Ensure the key matches that resource's region (regional endpoints reject global keys and vice versa).","Regenerate the key in Azure and update MicrosoftTranslatorApiKey.","Test the endpoint with curl using the same header to see Azure's raw error."],"exampleFix":"// before\nthrow new Exception($\"Could not get access token via {tokenEndpoint}: {result}\");\n\n// after - branch on the common 401/403 to give an actionable hint\nvar hint = response.StatusCode == HttpStatusCode.Unauthorized\n    ? \" (Azure rejected the API key - check MicrosoftTranslatorApiKey)\"\n    : response.StatusCode == HttpStatusCode.Forbidden\n        ? \" (Key region may not match this endpoint)\"\n        : string.Empty;\nthrow new Exception($\"Could not get access token via {tokenEndpoint}: {result}{hint}\");","handlingStrategy":"validation","validationCode":"// Validate the token endpoint shape before the POST\nvar endpoint = Configuration.Settings.Tools.MicrosoftTranslatorTokenEndpoint;\nif (string.IsNullOrWhiteSpace(endpoint))\n    throw new InvalidOperationException(\"Microsoft Translator token endpoint is not set.\");\nif (!Uri.TryCreate(endpoint, UriKind.Absolute, out var uri) || uri.Scheme != Uri.UriSchemeHttps)\n    throw new InvalidOperationException($\"Token endpoint must be an absolute HTTPS URL: {endpoint}\");\nif (!endpoint.Contains(\"issueToken\", StringComparison.OrdinalIgnoreCase))\n    throw new InvalidOperationException($\"Token endpoint should be an issueToken URL: {endpoint}\");","typeGuard":"public static bool IsValidAzureTokenEndpoint(string endpoint)\n    => Uri.TryCreate(endpoint, UriKind.Absolute, out var u)\n    && u.Scheme == Uri.UriSchemeHttps\n    && endpoint.Contains(\"issueToken\", StringComparison.OrdinalIgnoreCase);","tryCatchPattern":"try\n{\n    translator.Initialize();\n}\ncatch (Exception ex) when (ex.InnerException?.Message.Contains(\"Could not get access token\") == true)\n{\n    throw new InvalidOperationException(\"Azure token endpoint rejected the key - verify endpoint region and key.\", ex);\n}","preventionTips":["Copy the token endpoint verbatim from the Azure resource blade.","Keep key region and endpoint region in sync.","Health-check the endpoint with curl + the Ocp-Apim-Subscription-Key header during setup.","Regenerate keys in Azure when staff turnover occurs and update settings."],"tags":["api","auth","azure","translation","configuration"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}