duplicati/duplicati · error · Exception

Failed to deserialize delete file response

Error message

Failed to deserialize delete file response

What it means

Thrown inside DeleteAsync when JsonSerializer.Deserialize<pCloudDeleteResponse>(content) returns null after a successful HTTP response. Same System.Text.Json null-token behavior as the other pCloud operations. Generic Exception indicating the delete response body was null/invalid despite a 2xx status.

Source

Thrown at Duplicati/Library/Backend/pCloud/pCloudBackend.cs:423

    /// <param name="cancellationToken">CancellationToken that is combined with internal timeout token</param>
    /// <returns></returns>
    /// <exception cref="FileMissingException">FileMissingException when file is not found</exception>
    /// <exception cref="Exception">Exceptions arising from either code execution or business logic when return code from pcloud indicates an error.</exception>
    public async Task DeleteAsync(string remotename, CancellationToken cancellationToken)
    {
        using var request = CreateRequest($"/deletefile?fileid={await GetFileId(remotename, cancellationToken).ConfigureAwait(false)}", HttpMethod.Get);

        using var response = await Utility.Utility.WithTimeout(_Timeouts.ShortTimeout, cancellationToken,
            ct => _HttpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead, ct)
        ).ConfigureAwait(false);

        response.EnsureSuccessStatusCode();

        var content = await Utility.Utility.WithTimeout(_Timeouts.ShortTimeout, cancellationToken,
            ct => response.Content.ReadAsStringAsync(ct)
        ).ConfigureAwait(false);
        var deleteFileResponse = JsonSerializer.Deserialize<pCloudDeleteResponse>(content)
            ?? throw new Exception("Failed to deserialize delete file response");

        // If no error code is matched, result was == 0 so it successfully created the folder
        if (deleteFileResponse.result == 2009)
            throw new FileMissingException();

        if (pCloudErrorList.ErrorMessages.TryGetValue(deleteFileResponse.result, out var message))
            throw new Exception(message);

        if (deleteFileResponse.result != 0)
            throw new Exception(
                Strings.pCloudBackend.FailedWithUnexpectedErrorCode("delete", deleteFileResponse.result));
    }

    /// <summary>
    /// Implementation of interface function to return hosnames used by the backend
    /// </summary>
    /// <param name="cancellationToken">CancellationToken, in this call not used.</param>
    /// <returns></returns>

View on GitHub (pinned to 3f348be3e3)

Solutions

  1. Log the raw response body to diagnose.
  2. Verify the file is actually gone by listing the folder afterward (the delete may have succeeded).
  3. Retry idempotently — DeleteAsync on an already-deleted file surfaces as result 2009 / FileMissingException.
  4. Update pCloudDeleteResponse if the API envelope changed.

Example fix

// before: null body is a hard error, file may already be deleted
var deleteFileResponse = JsonSerializer.Deserialize<pCloudDeleteResponse>(content)
    ?? throw new Exception("Failed to deserialize delete file response");

// after: surface raw body for diagnosis
var deleteFileResponse = JsonSerializer.Deserialize<pCloudDeleteResponse>(content);
if (deleteFileResponse is null)
    throw new Exception($"Failed to deserialize delete file response; raw: {content}");
Defensive patterns

Strategy: retry

Validate before calling

// Inspect the delete response body
if (string.IsNullOrWhiteSpace(content) || content.Trim() == "null")
    Console.Error.WriteLine("delete returned null body; verify file is gone");

Try / catch

try { await backend.DeleteAsync(remotename, ct); }
catch (Exception ex) when (ex.Message == "Failed to deserialize delete file response")
{
    // delete may have succeeded; list to confirm; retry idempotently if needed
}

Prevention

When it happens

Trigger: /deletefile returns HTTP success but the JSON body is the literal null token or maps to a null reference. Reached after EnsureSuccessStatusCode (line 417), so transport succeeded but the body is malformed.

Common situations: Transient server serialization issue; API response-shape change for delete; proxy returning an empty/null body; the file was deleted but the response envelope was non-standard.

Related errors


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