signalapp/Signal-Server · error · InternalServerErrorException
failure during delivery
Error message
failure during delivery
What it means
Thrown as HTTP 500 when at least one per-recipient delivery future in a multi-recipient send completes exceptionally (ExecutionException). The server logs the underlying cause and returns InternalServerErrorException 'failure during delivery'.
Solutions
- Retry the send; partial failures are often transient
- Check server logs for the logged underlying cause to identify the failing recipient
- If persistent, remove/re-resolve the problematic recipient's devices and resend
Defensive patterns
Strategy: retry
Try / catch
try { await send(msg); } catch (e) { if (e.status === 500 && e.message === 'failure during delivery') await withBackoff(() => send(msg)); else throw e; } Prevention
- Retry transient partial failures
- Verify recipient device registration state before sending
- Resync device lists if failures persist for a specific contact
When it happens
Trigger: One or more individual recipient message deliveries fail (storage/registration errors, downstream message-send exceptions) while the batch is being fanned out.
Common situations: A destination account in an inconsistent state; transient storage layer failure during a large story send.
Related errors
- interrupted during delivery
- delivery cancelled
- Only primary devices may register attestations
- Invalid action:
- Multi-recipient messages must be addressed to ACI service…
AI-assisted analysis of signalapp/Signal-Server@100ab61c82 (2026-09-09).
Data as JSON: /api/errors/90266364577de1fe.
Report an issue: GitHub.
Appendix: source
Thrown at service/src/main/java/org/whispersystems/textsecuregcm/controllers/MessageController.java:658
try {
if (!resolvedRecipients.isEmpty()) {
messageSender.sendMultiRecipientMessage(multiRecipientMessage,
resolvedRecipients,
timestamp, isStory,
ephemeral,
urgent,
context.getHeaderString(HttpHeaders.USER_AGENT)).get();
}
} catch (final InterruptedException e) {
logger.error("interrupted while delivering multi-recipient messages", e);
throw new InternalServerErrorException("interrupted during delivery");
} catch (final CancellationException e) {
logger.error("cancelled while delivering multi-recipient messages", e);
throw new InternalServerErrorException("delivery cancelled");
} catch (final ExecutionException e) {
logger.error("partial failure while delivering multi-recipient messages", e.getCause());
throw new InternalServerErrorException("failure during delivery");
} catch (final MessageTooLargeException e) {
throw new WebApplicationException(Status.REQUEST_ENTITY_TOO_LARGE);
} catch (final MultiRecipientMismatchedDevicesException e) {
final List<AccountMismatchedDevices> accountMismatchedDevices =
e.getMismatchedDevicesByServiceIdentifier().entrySet().stream()
.filter(entry -> !entry.getValue().missingDeviceIds().isEmpty() || !entry.getValue().extraDeviceIds().isEmpty())
.map(entry -> new AccountMismatchedDevices(entry.getKey(),
new MismatchedDevicesResponse(entry.getValue().missingDeviceIds(), entry.getValue().extraDeviceIds())))
.toList();
if (!accountMismatchedDevices.isEmpty()) {
throw new WebApplicationException(Response
.status(409)
.type(MediaType.APPLICATION_JSON_TYPE)
.entity(accountMismatchedDevices)
.build());
}
View on GitHub (pinned to 100ab61c82)