duplicati/duplicati · error · Exception

Failed to parse response

Error message

Failed to parse response

What it means

Thrown in PutAsync (B2.cs:370) after a successful file upload. The HTTP status was 2xx (EnsureSuccessStatusCode passed), but deserializing the response body as UploadFileResponse using Newtonsoft.Json returned null. This means the body was empty, contained literal JSON null, or did not match any properties of UploadFileResponse.

Source

Thrown at Duplicati/Library/Backend/Backblaze/B2.cs:370

            request.Headers.TryAddWithoutValidation("Authorization", uploadUrlData.AuthorizationToken);
            request.Headers.Add("X-Bz-Content-Sha1", sha1);
            request.Headers.Add("X-Bz-File-Name", _urlencodedPrefix + Utility.UrlEncoding.UrlPathEncode(remotename));
            request.Content = new StreamContent(timeoutStream);

            request.Content.Headers.Add("Content-Type", "application/octet-stream");
            request.Content.Headers.Add("Content-Length", timeoutStream.Length.ToString());

            var response = await _httpClient.UploadStream(request, cancelToken).ConfigureAwait(false);
            response.EnsureSuccessStatusCode();

            var rdata = await response.Content.ReadAsStreamAsync(cancelToken).ConfigureAwait(false);

            UploadFileResponse fileinfo;
            using (var tr = new StreamReader(rdata))
            await using (var jr = new Newtonsoft.Json.JsonTextReader(tr))
                fileinfo = new Newtonsoft.Json.JsonSerializer().Deserialize<UploadFileResponse>(jr)
                    ?? throw new Exception("Failed to parse response");

            // Delete old versions
            if (_filecache!.ContainsKey(remotename))
                await DeleteAsync(remotename, cancelToken).ConfigureAwait(false);

            _filecache[remotename] =
            [
                new FileEntity
                {
                    FileID = fileinfo.FileID,
                    FileName = fileinfo.FileName,
                    Action = "upload",
                    Size = fileinfo.ContentLength,
                    UploadTimestamp = (long)(DateTime.UtcNow - Utility.Utility.EPOCH).TotalMilliseconds
                }
            ];
        }
        catch (Exception ex)

View on GitHub (pinned to 3f348be3e3)

Solutions

  1. Retry the upload to rule out transient response corruption or B2 maintenance
  2. Inspect network path for proxies or appliances intercepting upload traffic to the B2 upload URL
  3. Update Duplicati to the latest version in case of B2 API response schema changes
Defensive patterns

Strategy: retry

Try / catch

var maxRetries = 3;
for (int attempt = 0; attempt < maxRetries; attempt++)
{
    try { await backend.PutAsync(remotename, stream, cancelToken); break; }
    catch (Exception ex) when (ex.Message == "Failed to parse response" && attempt < maxRetries - 1)
    {
        // Upload HTTP succeeded but response was unparseable; retry the upload
        await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)), cancelToken);
    }
}

Prevention

When it happens

Trigger: PutAsync completes the HTTP upload to the B2 upload URL. response.Content.ReadAsStreamAsync provides the body. A StreamReader + Newtonsoft.Json.JsonTextReader feeds into JsonSerializer.Deserialize<UploadFileResponse>. If the result is null, the upload response could not be parsed.

Common situations: Network intermediary (proxy, CDN, firewall) truncating or replacing the upload response; B2 API returning an unexpected response format during maintenance; response encoding issue (e.g. double-gzip); Duplicati version incompatible with a B2 API schema change.

Understand the failure class

Related errors


AI-assisted analysis of duplicati/duplicati@3f348be3e3 (2026-08-13). Data as JSON: /api/errors/8f832b865026ee64. Report an issue: GitHub.