{"record":{"id":"7e14989f4f958073","repo":"duplicati/duplicati","slug":"download-url-is-missing-from-authorization-respons","errorCode":null,"errorMessage":"Download URL is missing from authorization response","messagePattern":"Download URL is missing from authorization response","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"Duplicati/Library/Backend/Backblaze/B2AuthHelper.cs","lineNumber":140,"sourceCode":"                {\r\n                    response = await _httpClient.SendAsync(request, ct).ConfigureAwait(false);\r\n                    response.EnsureSuccessStatusCode();\r\n\r\n                    return await ReadJsonResponseAsync<ApiAuthResponse>(response, ct).ConfigureAwait(false)\r\n                        ?? throw new Exception(\"Failed to parse authorization response\");\r\n                }).ConfigureAwait(false);\r\n\r\n                if (string.IsNullOrWhiteSpace(authResponse.AccountID))\r\n                    throw new Exception(\"Account ID is missing from authorization response\");\r\n\r\n                if (string.IsNullOrWhiteSpace(authResponse.APIUrl))\r\n                    throw new Exception(\"API URL is missing from authorization response\");\r\n\r\n                if (string.IsNullOrWhiteSpace(authResponse.AuthorizationToken))\r\n                    throw new Exception(\"Authorization token is missing from authorization response\");\r\n\r\n                if (string.IsNullOrWhiteSpace(authResponse.DownloadUrl))\r\n                    throw new Exception(\"Download URL is missing from authorization response\");\r\n\r\n                authResponse.APIUrl = DropTrailingSlashes(authResponse.APIUrl);\r\n                authResponse.DownloadUrl = DropTrailingSlashes(authResponse.DownloadUrl);\r\n                _configExpires = DateTime.UtcNow + TimeSpan.FromMinutes(CACHE_EXPIRATION_MINUTES);\r\n\r\n                return _CachedAuthResponse = new AuthResponse(authResponse.AccountID, authResponse.APIUrl, authResponse.AuthorizationToken, authResponse.DownloadUrl);\r\n            }\r\n            catch (Exception ex)\r\n            {\r\n                var clientError = false;\r\n\r\n                try\r\n                {\r\n                    // Only retry once on client errors\r\n                    if (ex is HttpRequestException { StatusCode: not null } exception)\r\n                    {\r\n                        var sc = (int)exception.StatusCode;\r\n                        clientError = sc is >= 400 and <= 499;\r","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/duplicati/duplicati/blob/3f348be3e33f5d72d414e3ad55839c2ba34dda67/Duplicati/Library/Backend/Backblaze/B2AuthHelper.cs#L122-L158","documentation":"Thrown in B2AuthHelper.GetConfigAsync (B2AuthHelper.cs:140) when the auth response parsed successfully but the downloadUrl field is empty or whitespace. ApiAuthResponse.DownloadUrl maps to the downloadUrl JSON property and is nullable string?. The downloadUrl is used for file download operations (GetAsync). Retried up to 5 times before surfacing.","triggerScenarios":"The deserialized ApiAuthResponse lacks downloadUrl. After 5 retries, the bare Exception propagates. This field is needed for constructing download URLs in GetAsync.","commonSituations":"Proxy stripping downloadUrl from the auth response; B2 API schema change; response truncation by intermediary.","solutions":["Verify direct connectivity to api.backblazeb2.com without TLS interception","Regenerate the application key and retry","Retry after a few minutes to rule out transient B2 issues"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { var config = await b2AuthHelper.GetConfigAsync(cancelToken); }\ncatch (Exception ex) when (ex.Message == \"Download URL is missing from authorization response\")\n{\n    logger.LogError(ex, \"B2 auth response missing downloadUrl after retries\");\n    throw;\n}","preventionTips":["Verify direct connectivity to api.backblazeb2.com without TLS interception","Regenerate the application key and retry authentication","Retry after a few minutes to rule out transient B2 API issues"],"tags":["b2","authentication","api-response","validation"],"backgroundTag":null,"analyzedSha":"3f348be3e33f5d72d414e3ad55839c2ba34dda67","analyzedAt":"2026-08-13T16:48:27.008Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}