TryGhost/Ghost · error · ValidationError

Subject is required

Error message

Subject is required

What it means

Thrown by `validatePreviewData` (used by the automated-emails `preview` and `sendTestEmail` validators) when `frame.data.subject` is not a non-empty trimmed string. Ghost requires a subject before rendering/sending an email preview, so a missing or blank subject yields a 422 ValidationError on the `subject` property.

Source

Thrown at ghost/core/core/server/api/endpoints/utils/validators/input/automated_emails.js:78

    }

    return Promise.resolve();
};

const validateOptionalStringField = (value, errorMessage) => {
    if (value !== undefined && value !== null && typeof value !== 'string') {
        throw new ValidationError({
            message: errorMessage
        });
    }
};

const validatePreviewData = (frame) => {
    const subject = frame.data.subject;
    const lexical = frame.data.lexical;

    if (typeof subject !== 'string' || !subject.trim()) {
        throw new ValidationError({
            message: tpl(messages.subjectRequired),
            property: 'subject'
        });
    }

    if (typeof lexical !== 'string' || !lexical.trim()) {
        throw new ValidationError({
            message: tpl(messages.lexicalRequired),
            property: 'lexical'
        });
    }

    try {
        JSON.parse(lexical);
    } catch (e) {
        throw new ValidationError({
            message: tpl(messages.invalidLexical),
            property: 'lexical'

View on GitHub (pinned to 47d8b0e2ad)

Solutions

  1. Ensure the request body includes `subject` as a non-empty string.
  2. Trim and validate the subject client-side before submitting.
  3. Confirm the JSON serialization includes the subject key.

Example fix

// before
await api.emailPreview.send({data: {lexical, email: 'a@b.com'}}); // subject missing

// after
await api.emailPreview.send({data: {subject: 'Welcome', lexical, email: 'a@b.com'}});
Defensive patterns

Strategy: validation

Validate before calling

function isValidSubject(s: unknown): s is string {
    return typeof s === 'string' && s.trim().length > 0;
}
if (!isValidSubject(payload.subject)) {
    throw new Error('subject must be a non-empty string');
}

Type guard

function isNonEmptyString(v: unknown): v is string {
    return typeof v === 'string' && v.trim().length > 0;
}

Prevention

When it happens

Trigger: A POST to the email preview/test endpoint omits `subject`, sends it as a non-string type, or sends a whitespace-only string.

Common situations: Frontend sends the preview request before the subject field is filled; JSON payload drops the subject key; subject is sent as `null` or an empty string; automated client forgetting required fields.

Related errors


AI-assisted analysis of TryGhost/Ghost@47d8b0e2ad (2026-08-13). Data as JSON: /api/errors/d7b47bbacf33f58a. Report an issue: GitHub.