signalapp/Signal-Server · error · DeviceLimitExceededException

return Response.status(411)

Error message

return Response.status(411)

What it means

The DeviceLimitExceededExceptionMapper converts a DeviceLimitExceededException into HTTP 411 (Length Required — Signal reuses this code) with a JSON body of DeviceLimitExceededDetails containing currentDevices and maxDevices. It signals the account has hit the server's maximum number of linked devices, so a new device link/provision request is rejected.

Solutions

  1. Unlink existing devices (via the primary device's linked-devices screen or the device API) before linking a new one
  2. Reuse an existing linked device instead of provisioning another
  3. Raise the max device limit in server configuration if legitimate use requires it
  4. Audit for scripts leaking device provisioning calls in a loop

Example fix

// before
linkNewDevice(account);
// after
if (deviceList.size() >= maxDevices) {
  unlinkOldestDevice(deviceList);
}
linkNewDevice(account);
Defensive patterns

Strategy: validation

Validate before calling

// count linked devices before attempting to provision a new one
if (account.getDevices().size() >= serverMaxDevices) {
  throw new IllegalStateException("unlink a device first");
}

Type guard

boolean canLinkDevice(Account a, int maxDevices) {
  return a.getDevices().size() < maxDevices;
}

Try / catch

try { linkDevice(account); }
catch (DeviceLimitExceededException e) {
  showUserDeviceList(e.getCurrentDevices(), e.getMaxDevices()); // prompt unlink
}

Prevention

When it happens

Trigger: Any endpoint that throws DeviceLimitExceededException — typically attempting to provision/link a new device when the account already has maxDevices linked devices.

Common situations: Users accumulating dormant linked desktops/tablets over years; automations repeatedly provisioning test devices against one account; low maxDevices setting in server config making the limit easy to hit.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at service/src/main/java/org/whispersystems/textsecuregcm/mappers/DeviceLimitExceededExceptionMapper.java:19

/*
 * Copyright 2013-2020 Signal Messenger, LLC
 * SPDX-License-Identifier: AGPL-3.0-only
 */

package org.whispersystems.textsecuregcm.mappers;


import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;
import org.whispersystems.textsecuregcm.controllers.DeviceLimitExceededException;

@Provider
public class DeviceLimitExceededExceptionMapper implements ExceptionMapper<DeviceLimitExceededException> {
  @Override
  public Response toResponse(DeviceLimitExceededException exception) {
    return Response.status(411)
                   .entity(new DeviceLimitExceededDetails(exception.getCurrentDevices(),
                                                          exception.getMaxDevices()))
                   .build();
  }

  private static class DeviceLimitExceededDetails {
    @JsonProperty
    private int current;
    @JsonProperty
    private int max;

    public DeviceLimitExceededDetails(int current, int max) {
      this.current = current;
      this.max     = max;
    }
  }
}

View on GitHub (pinned to 100ab61c82)