signalapp/Signal-Server · error · SecureValueRecoveryException

Failed to delete backup

Error message

Failed to delete backup

What it means

SecureValueRecoveryClient.removeData DELETEs a user's SVR backup and expects a success status. On failure, it throws SecureValueRecoveryException('Failed to delete backup', status) after logging; only explicitly allowed error codes are swallowed and treated as success. Callers (account deletion flows) get this exception whenever the SVR service rejects the deletion.

Solutions

  1. Check the logged status code ('Failed to delete svr entry ... with status <code>') to identify the SVR rejection reason.
  2. If the status is benign (e.g. 404 for an already-deleted backup), add it to allowedErrors in removeData.
  3. Verify connectivity/credentials to the Secure Value Recovery service.
  4. Retry the deletion if the failure was transient (5xx); account deletion jobs typically retry.
  5. Catch SecureValueRecoveryException in the deletion flow and proceed/degrade appropriately per product policy.

Example fix

// before
throw new SecureValueRecoveryException("Failed to delete backup", String.valueOf(response.statusCode()));

// after: treat 404 as already-deleted
Set<Integer> allowedErrors = Set.of(401, 403, 404);
if (allowedErrors.contains(response.statusCode())) {
  return null;
}
throw new SecureValueRecoveryException("Failed to delete backup", String.valueOf(response.statusCode()));
Defensive patterns

Strategy: try-catch

Try / catch

try {
  svrClient.removeData(accountIdentifier);
} catch (SecureValueRecoveryException e) {
  logger.warn("SVR delete failed with status {} — continuing account deletion", e.getStatus());
  // decide per policy: retry later, or proceed since local deletion is authoritative
}

Prevention

When it happens

Trigger: Calling removeData (e.g. during account deletion) when the SVR service returns a non-success HTTP status not in allowedErrors — service outage, unknown account/backup id, or authentication failure against the SVR peer.

Common situations: SVR backend down or degraded during bulk account deletions, mismatched credentials/config for the remote SVR service, or new status codes (e.g. 410 Gone, 404) not yet added to allowedErrors.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of signalapp/Signal-Server@100ab61c82 (2026-09-09). Data as JSON: /api/errors/56415642b7a90721. Report an issue: GitHub.

Appendix: source

Thrown at service/src/main/java/org/whispersystems/textsecuregcm/securevaluerecovery/SecureValueRecoveryClient.java:93

    final HttpRequest request = HttpRequest.newBuilder()
        .uri(deleteUri)
        .DELETE()
        .header(HttpHeaders.AUTHORIZATION, basicAuthHeader(credentials))
        .build();

    return httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString()).thenApply(response -> {
      if (HttpUtils.isSuccessfulResponse(response.statusCode())) {
        return null;
      }

      final List<Integer> allowedErrors = allowedDeletionErrorStatusCodes.get();
      if (allowedErrors.contains(response.statusCode())) {
        logger.warn("Ignoring failure to delete svr entry for identifier {} with status {}",
            userIdentifier, response.statusCode());
        return null;
      }
      logger.warn("Failed to delete svr entry for identifier {} with status {}", userIdentifier, response.statusCode());
      throw new SecureValueRecoveryException("Failed to delete backup", String.valueOf(response.statusCode()));
    });
  }

}

View on GitHub (pinned to 100ab61c82)