TryGhost/Ghost · error · EmailFailedError
email.error
Error message
email.error
What it means
retryEmailTask is an ember-concurrency task that retries sending a post email and polls the email record's status until 'submitted' or a timeout. When email.reload() returns status === 'failed', it throws EmailFailedError(email.error) where email.error is the backend-provided failure reason. The catch block checks e.name === 'EmailFailedError' and surfaces the message as newEmailErrorMessage. The error is not a thrown-to-caller error — it is caught internally and converted to a UI state.
Source
Thrown at apps/ember-admin/app/components/editor/modals/publish-flow/complete-with-email-error.js:48
*retryEmailTask() {
this.retryErrorMessage = null;
try {
let email = yield this.args.publishOptions.post.email.retry();
let pollTimeout = 0;
if (email && email.status !== 'submitted') {
while (pollTimeout < CONFIRM_EMAIL_MAX_POLL_LENGTH) {
yield timeout(CONFIRM_EMAIL_POLL_LENGTH);
pollTimeout += CONFIRM_EMAIL_POLL_LENGTH;
email = yield email.reload();
if (email.status === 'submitted') {
break;
}
if (email.status === 'failed') {
throw new EmailFailedError(email.error);
}
}
}
this.args.setCompleted();
return email;
} catch (e) {
// update "failed" state if email fails again
if (e && e.name === 'EmailFailedError') {
this.newEmailErrorMessage = e.message;
return false;
}
if (e) {
let errorMessage = '';
if (isServerUnreachableError(e)) {View on GitHub (pinned to 47d8b0e2ad)
Solutions
- Inspect the email.error message displayed in the UI (newEmailErrorMessage) — it carries the provider's failure reason (e.g. 'Mailgun domain not verified').
- Verify the email provider configuration in Ghost Labs/settings: Mailgun domain/API key or custom SMTP credentials.
- Check the Mailgun/SMTP provider dashboard for the specific failure (bounces, blocks, domain verification).
- If 'partially' failed (isPartialError), some recipients received the email — review the recipient list and re-send to the failed subset after fixing the provider issue.
Defensive patterns
Strategy: try-catch
Type guard
function isEmailFailedError(e: unknown): e is Error {
return e instanceof Error && (e as any).name === 'EmailFailedError';
} Try / catch
// the task already catches internally; this is the pattern it uses:
try {
yield this.args.publishOptions.post.email.retry();
// ... polling loop ...
} catch (e) {
if (isEmailFailedError(e)) {
this.newEmailErrorMessage = e.message; // provider's failure reason
return false;
}
// other errors (network, unknown)
} Prevention
- Verify Mailgun domain verification or SMTP credentials before scheduling email sends.
- Monitor email.error values across failures to detect provider config drift early.
- For partial failures, review the recipient list and re-send only to the failed segment after fixing the provider issue.
- Use the isPartialError check (message includes 'partially') to distinguish total vs partial send failures in the UI.
When it happens
Trigger: The email send (Mailgun/SMTP) failed server-side and the email record's status transitioned to 'failed' with an error string in email.error. The polling loop (up to CONFIRM_EMAIL_MAX_POLL_LENGTH) observes this status. Causes: Mailgun API error, SMTP connection failure, invalid recipient list, bounce/blocklist, or rate limit from the email provider. The email.error field carries the provider-specific message.
Common situations: A publication's Mailgun domain is not verified, causing all sends to fail. An SMTP integration (custom mailer) has wrong credentials. The recipient list contains addresses that cause a hard bounce on a previous send, triggering provider-level blocks. A large blast hits the provider rate limit and some emails fail.
Related errors
- Please verify your email settings
- No staff invitation email found for ${email}${detail}
- No staff invitation email found for ${email}
- Timeout after ${timeoutMs}ms waiting for search results
- post.email.error
AI-assisted analysis of TryGhost/Ghost@47d8b0e2ad (2026-08-13).
Data as JSON: /api/errors/eb91be7728212f3b.
Report an issue: GitHub.