ellite/Wallos · error · Exception
STOP_CRITICAL
STOP_CRITICAL
Error message
You must provide at least one recipient email address.
What it means
preSend() throws 'You must provide at least one recipient email address.' with severity STOP_CRITICAL when, after all recipient queues are replayed, count($to)+count($cc)+count($bcc) is zero. send() calls preSend(), so the whole send aborts. The localized text comes from $this->lang('provide_address').
Solutions
- Call addAddress() (or addCC/addBCC) at least once before send()
- Check the return value / exceptions of every addAddress() so failed additions are not silently ignored
- Guard before sending: if (!$mail->getToAddresses() && !$mail->getCcAddresses() && !$mail->getBccAddresses()) skip or report
- When sending conditionally, ensure the recipient list is populated from a validated data source
Example fix
// before
$mail->send(); // throws if no recipients
// after
if (empty($mail->getToAddresses()) && empty($mail->getCcAddresses()) && empty($mail->getBccAddresses())) {
throw new RuntimeException('No recipients to send to');
}
$mail->send(); Defensive patterns
Strategy: try-catch
Validate before calling
if (count($mail->getToAddresses()) + count($mail->getCcAddresses()) + count($mail->getBccAddresses()) === 0) { throw new LogicException('No recipients set'); } Try / catch
try { $mail->send(); } catch (PHPMailer\PHPMailer\Exception $e) { if ($e->getCode() === PHPMailer::STOP_CRITICAL && str_contains($e->getMessage(), 'recipient')) { /* recipient list empty */ } throw $e; } Prevention
- Assert recipients exist before send() in a small wrapper around PHPMailer
- Check addAddress() return values; a false return means the recipient was not added
- Avoid filtering recipient arrays to empty without a guard
- Centralize mail-sending in one service so recipient setup can be enforced
When it happens
Trigger: Calling $mail->send() with no addAddress/addCC/addBCC (and no RecipientsQueue entries); addAddress calls that silently failed (returned false without exceptions enabled) also lead here because the recipient count stays zero.
Common situations: Building mail dynamically where recipient list ends up empty (filtered array), addAddress failing earlier due to invalid addresses while exceptions were disabled so errors were swallowed, refactored code that moved recipient setup behind a condition that no longer runs.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
AI-assisted analysis of ellite/Wallos@52820e87ca (2026-09-13).
Data as JSON: /api/errors/7d1e8cd7674100db.
Report an issue: GitHub.
Appendix: source
Thrown at libs/PHPMailer/PHPMailer.php:1569
&& ((\PHP_VERSION_ID >= 70000 && \PHP_VERSION_ID < 70017)
|| (\PHP_VERSION_ID >= 70100 && \PHP_VERSION_ID < 70103))
&& ini_get('mail.add_x_header') === '1'
&& stripos(PHP_OS, 'WIN') === 0
) {
trigger_error($this->lang('buggy_php'), E_USER_WARNING);
}
try {
$this->error_count = 0; //Reset errors
$this->mailHeader = '';
//Dequeue recipient and Reply-To addresses with IDN
foreach (array_merge($this->RecipientsQueue, $this->ReplyToQueue) as $params) {
$params[1] = $this->punyencodeAddress($params[1]);
call_user_func_array([$this, 'addAnAddress'], $params);
}
if (count($this->to) + count($this->cc) + count($this->bcc) < 1) {
throw new Exception($this->lang('provide_address'), self::STOP_CRITICAL);
}
//Validate From, Sender, and ConfirmReadingTo addresses
foreach (['From', 'Sender', 'ConfirmReadingTo'] as $address_kind) {
if ($this->{$address_kind} === null) {
$this->{$address_kind} = '';
continue;
}
$this->{$address_kind} = trim($this->{$address_kind});
if (empty($this->{$address_kind})) {
continue;
}
$this->{$address_kind} = $this->punyencodeAddress($this->{$address_kind});
if (!static::validateAddress($this->{$address_kind})) {
$error_message = sprintf(
'%s (%s): %s',
$this->lang('invalid_address'),
$address_kind,View on GitHub (pinned to 52820e87ca)