ellite/Wallos · error · Exception
$this->lang('empty_message')
Error message
$this->lang('empty_message') What it means
PHPMailer throws 'empty_message' (STOP_CRITICAL) in createBody() when the composed message body ends up empty and the instance has exceptions enabled. It signals that send() cannot proceed because there is no HTML or plain-text body to transmit.
Solutions
- Set $mail->Body (and optionally $mail->AltBody) to a non-empty string before send()
- If using msgHTML(), verify the source HTML is non-empty after rendering
- Set $mail->isHTML(true) with a real body instead of relying on defaults
Example fix
// before
$mail->msgHTML($template->render([])); // renders empty
// after
$html = $template->render(['user' => $user]);
if (trim($html) === '') { throw new RuntimeException('Template rendered empty body'); }
$mail->msgHTML($html); Defensive patterns
Strategy: validation
Validate before calling
if (trim($mail->Body) === '' && trim($mail->AltBody) === '') { throw new LogicException('PHPMailer body is empty; set Body/AltBody before send()'); } Type guard
function hasNonEmptyString($v): bool { return is_string($v) && trim($v) !== ''; } Try / catch
try { $mail->send(); } catch (PHPMailer\PHPMailer\Exception $e) { if (str_contains($e->getMessage(), 'empty_message') || str_contains($e->getMessage(), 'Message body empty')) { /* fix body */ } throw $e; } Prevention
- Always set Body or call msgHTML() with verified non-empty HTML
- Assert the template render output is non-empty before assigning it
- Add a pre-send invariant check for Body/AltBody in your mailer wrapper
When it happens
Trigger: Calling send()/preSend() when $this->Body and $this->AltBody are both empty (e.g. msgHTML() was given an empty string or a body that rendered to nothing), or a body-building branch produced nothing.
Common situations: Rendering a Twig/Smarty template that outputs only whitespace, calling msgHTML(''), forgetting to set Body/AltBody, or clearing the body after an earlier send() call.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
AI-assisted analysis of ellite/Wallos@52820e87ca (2026-09-13).
Data as JSON: /api/errors/d3721ba51bbc59d4.
Report an issue: GitHub.
Appendix: source
Thrown at libs/PHPMailer/PHPMailer.php:3040
$body .= static::$LE;
$body .= $this->attachAll('inline', $this->boundary[3]);
$body .= static::$LE;
$body .= $this->endBoundary($this->boundary[2]);
$body .= static::$LE;
$body .= $this->attachAll('attachment', $this->boundary[1]);
break;
default:
//Catch case 'plain' and case '', applies to simple `text/plain` and `text/html` body content types
//Reset the `Encoding` property in case we changed it for line length reasons
$this->Encoding = $bodyEncoding;
$body .= $this->encodeString($this->Body, $this->Encoding);
break;
}
if ($this->isError()) {
$body = '';
if ($this->exceptions) {
throw new Exception($this->lang('empty_message'), self::STOP_CRITICAL);
}
} elseif ($this->sign_key_file) {
try {
if (!defined('PKCS7_TEXT')) {
throw new Exception($this->lang('extension_missing') . 'openssl');
}
$file = tempnam(sys_get_temp_dir(), 'srcsign');
$signed = tempnam(sys_get_temp_dir(), 'mailsign');
file_put_contents($file, $body);
//Workaround for PHP bug https://bugs.php.net/bug.php?id=69197
if (empty($this->sign_extracerts_file)) {
$sign = @openssl_pkcs7_sign(
$file,
$signed,
'file://' . realpath($this->sign_cert_file),
['file://' . realpath($this->sign_key_file), $this->sign_key_pass],View on GitHub (pinned to 52820e87ca)