TryGhost/Ghost · error · ValidationError
The server did not receive a valid email
Error message
The server did not receive a valid email
What it means
Thrown by the `sendTestEmail` validator when `frame.data.email` is not a string or fails `validator.isEmail`. Before sending a test email, Ghost validates the recipient address format; an invalid address yields a 422 ValidationError with `invalidEmailReceived`. After this check, `validatePreviewData` also runs.
Source
Thrown at ghost/core/core/server/api/endpoints/utils/validators/input/automated_emails.js:131
validateOptionalStringField(senderName, 'Sender name must be a string');
validateOptionalStringField(senderEmail, 'Sender email must be a string');
validateOptionalStringField(senderReplyTo, 'Reply-to email must be a string');
},
verifySenderUpdate(apiConfig, frame) {
if (typeof frame.data.token !== 'string' || !frame.data.token.trim()) {
throw new ValidationError({
message: tpl(messages.tokenRequired)
});
}
},
preview(apiConfig, frame) {
validatePreviewData(frame);
},
sendTestEmail(apiConfig, frame) {
const email = frame.data.email;
if (typeof email !== 'string' || !validator.isEmail(email)) {
throw new ValidationError({
message: tpl(messages.invalidEmailReceived)
});
}
validatePreviewData(frame);
}
};
View on GitHub (pinned to 47d8b0e2ad)
Solutions
- Validate the email address format client-side (regex or `validator.isEmail`) before sending.
- Ensure the `email` field is present and a non-empty valid string in the request body.
- Trim whitespace from the input before validation.
Example fix
// before
await api.email.sendTestEmail({data: {email: 'not-an-email', subject, lexical}});
// after
await api.email.sendTestEmail({data: {email: 'user@example.com', subject, lexical}}); Defensive patterns
Strategy: validation
Validate before calling
import validator from '@tryghost/validator';
function isValidEmail(v: unknown): boolean {
return typeof v === 'string' && validator.isEmail(v);
}
if (!isValidEmail(payload.email)) {
throw new Error('email must be a valid email address');
} Type guard
function isValidEmail(v: unknown): v is string {
return typeof v === 'string' && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v);
} Prevention
- Validate the email format client-side before sending a test email.
- Trim whitespace and confirm the `email` field is present in the payload.
- Use the same validator library Ghost uses to match server-side behavior.
When it happens
Trigger: A send-test-email request omits `email`, sends a non-string, or sends a syntactically invalid email address (missing `@`, bad domain, stray characters).
Common situations: Frontend submits before validating the email input; typo in the address; payload uses wrong key; empty string; user-provided address not sanitized.
Related errors
- Subject is required
- Email content is required
- Token is required
- Lexical must be a valid JSON string
- Cannot disconnect Stripe whilst you have active subscription
AI-assisted analysis of TryGhost/Ghost@47d8b0e2ad (2026-08-13).
Data as JSON: /api/errors/1de0bfcfca9426a3.
Report an issue: GitHub.