signalapp/Signal-Server · error · ClientErrorException

exceeded maximum uploadLength

Error message

exceeded maximum uploadLength

What it means

Before creating a message-backup upload descriptor, the controller validates the declared uploadLength against maxMessageBackupSize. If the declared size exceeds the limit, it throws ClientErrorException with HTTP 413 REQUEST_ENTITY_TOO_LARGE. The check uses the query parameter, not the actual body, so clients must declare their size honestly.

Solutions

  1. Reduce uploadLength to at most maxMessageBackupSize (obtain the current limit from the server's advertised max).
  2. Free space by removing old backups before re-uploading.
  3. Split the backup or upgrade the client to the latest version that respects current limits.
  4. If using uploadLength-less requests (default = max size), pass an explicit accurate length.

Example fix

// before
long length = backupBytes.length + extraAttachmentsBytes; // exceeds server max -> 413
// after
long length = backupBytes.length;
if (length > maxMessageBackupSize) {
  throw new BackupTooLargeException(); // surface to user before calling server
}
Defensive patterns

Strategy: validation

Validate before calling

long actual = backupBytes.length;
if (actual > maxMessageBackupSize) {
  throw new BackupTooLargeException(actual, maxMessageBackupSize); // fail before calling server
}

Try / catch

try {
  createUploadDescriptor(uploadLength);
} catch (ClientErrorException e) {
  if (e.getResponse().getStatus() == 413) {
    handleBackupTooLarge();
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the backup upload endpoint with ?uploadLength= greater than maxMessageBackupSize.

Common situations: Backups growing after a server-side limit reduction; clients rounding up or defaulting to an oversized length; uploading a full backup where only media quota differs; version skew between client assumption and server limit.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at service/src/main/java/org/whispersystems/textsecuregcm/controllers/ArchiveController.java:613

      @HeaderParam(X_SIGNAL_ZK_AUTH_SIGNATURE) final BackupAuthCredentialPresentationSignature signature,

      @Parameter(description = "The size of the message backup to upload in bytes")
      @QueryParam("uploadLength") final Optional<Long> uploadLength)
      throws BackupFailedZkAuthenticationException, BackupWrongCredentialTypeException, BackupPermissionException {
    if (account.isPresent()) {
      throw new BadRequestException("must not use authenticated connection for anonymous operations");
    }

    final AuthenticatedBackupUser backupUser =
        backupManager.authenticateBackupUser(presentation.presentation, signature.signature, userAgent);

    final boolean oversize = uploadLength
        .map(length -> length > maxMessageBackupSize)
        .orElse(false);

    backupMetrics.updateMessageBackupSizeDistribution(backupUser, oversize, uploadLength);
    if (oversize) {
      throw new ClientErrorException("exceeded maximum uploadLength", Response.Status.REQUEST_ENTITY_TOO_LARGE);
    }
    final BackupUploadDescriptor uploadDescriptor =
        backupManager.createMessageBackupUploadDescriptor(backupUser, uploadLength.orElse(maxMessageBackupSize));
    return new UploadDescriptorResponse(
        uploadDescriptor.cdn(),
        uploadDescriptor.key(),
        uploadDescriptor.headers(),
        uploadDescriptor.signedUploadLocation());
  }

  @GET
  @Path("/media/upload/form")
  @Produces(MediaType.APPLICATION_JSON)
  @Operation(
      summary = "Fetch media attachment upload form",
      description = """
          Retrieve an upload form that can be used to perform a resumable upload of an attachment. After uploading, the
          attachment can be copied into the backup at PUT /archives/media/.

View on GitHub (pinned to 100ab61c82)