RocketChat/Rocket.Chat · error · Error
error-invalid-email
error-invalid-email
Error message
error-invalid-email
What it means
Thrown by `sendOfflineMessage` when the destructured `email` field of the offline message data is falsy. The offline email needs a reply-to address, so the payload is rejected before any template/DNS work — a plain required-field gate, distinct from error 918's domain-validity check.
Source
Thrown at apps/meteor/server/lib/omnichannel/messages.ts:37
const dnsResolveMx = util.promisify(dns.resolveMx);
type OfflineMessageData = {
message: string;
name: string;
email: string;
department?: string;
host?: string;
};
export async function sendOfflineMessage(data: OfflineMessageData) {
if (!settings.get('Livechat_display_offline_form')) {
throw new Error('error-offline-form-disabled');
}
const { message, name, email, department, host } = data;
if (!email) {
throw new Error('error-invalid-email');
}
const emailMessage = `${message}`.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1<br>$2');
let html = '<h1>New livechat message</h1>';
if (host && host !== '') {
html = html.concat(`<p><strong>Sent from:</strong><a href='${host}'> ${host}</a></p>`);
}
html = html.concat(`
<p><strong>Visitor name:</strong> ${name}</p>
<p><strong>Visitor email:</strong> ${email}</p>
<p><strong>Message:</strong><br>${emailMessage}</p>`);
const fromEmail = settings.get<string>('From_Email').match(/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}\b/i);
let from: string;
if (fromEmail) {
from = fromEmail[0];View on GitHub (pinned to b2c16d5842)
Solutions
- Make the email field required and validated (non-empty, basic format) in the form before submission
- If building the payload in code, assert `data.email` is a non-empty string first
- For API consumers, return a 400-style validation message instead of surfacing the raw error
Example fix
// before
await sendOfflineMessage({ message, name, email: '' });
// after
if (!email || !/.+@.+\..+/.test(email)) {
throw new Error('A valid email is required');
}
await sendOfflineMessage({ message, name, email }); Defensive patterns
Strategy: validation
Validate before calling
if (!data.email || !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(data.email)) {
throw new Error('Email is required');
}
await sendOfflineMessage(data); Type guard
const hasContactEmail = (d: { email?: string }): boolean =>
typeof d.email === 'string' && d.email.trim().length > 0; Try / catch
try {
await sendOfflineMessage(data);
} catch (e) {
if (e instanceof Error && e.message === 'error-invalid-email') {
// mark the email input as required in the form
}
} Prevention
- Make email a required, validated input in every offline form frontend
- Assert payload shape in API wrappers before calling
- Trim and basic-format-check email client-side
When it happens
Trigger: Submitting the offline form with an empty email input — the widget/API did not enforce the field client-side, or the payload was constructed programmatically without an `email` key.
Common situations: Custom offline-form frontends that drop the email input or mark it optional; middleware stripping unknown/empty fields; users submitting with whitespace-only input that survives naive checks.
Related errors
- error-invalid-department
- error-invalid-email
- error-invalid-custom-field-value
- Missing required custom fields: ${errors.join(', ')}
- error-offline-form-disabled
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/57c56b996103685c.
Report an issue: GitHub.