TryGhost/Ghost · error · ValidationError
The body of a comment cannot be empty
Error message
The body of a comment cannot be empty
What it means
A ValidationError raised in the Comment model's `onSaving` hook after the raw HTML is passed through `sanitizeHtml` and trimmed. If the sanitized result is empty, the comment had no permitted content left after stripping disallowed tags/attributes. This prevents storing comments that consist solely of blocked markup or whitespace.
Source
Thrown at ghost/core/core/server/models/comment.js:160
const html = trimParagraphs(
sanitizeHtml(this.get('html'), {
allowedTags: ['p', 'br', 'a', 'blockquote'],
allowedAttributes: {
a: ['href', 'target', 'rel']
},
selfClosing: ['br'],
// Enforce _blank and safe URLs
transformTags: {
a: sanitizeHtml.simpleTransform('a', {
target: '_blank',
rel: 'ugc noopener noreferrer nofollow'
})
}
})
).trim();
if (html.length === 0) {
throw new ValidationError({
message: tpl(messages.emptyComment)
});
}
this.set('html', html);
}
},
orderAttributes: function orderAttributes() {
let keys = ghostBookshelf.Model.prototype.orderAttributes.call(this, arguments);
keys.push('count__likes');
keys.push('count__net_score');
keys.push('count__reports');
return keys;
},
onCreated: function onCreated(model, options) {
const result = ghostBookshelf.Model.prototype.onCreated.apply(this, arguments);
View on GitHub (pinned to 47d8b0e2ad)
Solutions
- Require at least one non-whitespace text character in the comment body on the client before posting.
- Strip HTML server-side in your own code and reject if no visible text remains.
- Review what tags the comment sanitizer currently allows and ensure the user's content uses allowed markup.
- If embedding media, use the supported comment feature set rather than raw disallowed tags.
Example fix
// before
await api.comments.add({html: '<br>'});
// after
const body = '<p>Great post, thanks!</p>';
if (!body.replace(/<[^>]*>/g, '').trim()) throw new Error('Comment has no text');
await api.comments.add({html: body}); Defensive patterns
Strategy: validation
Validate before calling
function hasCommentText(html) {
const text = String(html || '').replace(/<[^>]*>/g, '').trim();
return text.length > 0;
}
// if (!hasCommentText(body)) reject('Comment body is empty'); Type guard
const hasVisibleText = (html) => /<[a-z0-9]+[^>]*>(.*?\S.*?)<\/[a-z0-9]+>|\S/i.test(String(html || '')) && String(html || '').replace(/<[^>]*>/g, '').trim().length > 0;
Try / catch
try {
await api.comments.add({html: body});
} catch (err) {
if (err.type === 'ValidationError' && /cannot be empty/i.test(err.message)) notifyUser('Write something first');
else throw err;
} Prevention
- Require non-whitespace text in the comment input before enabling submit.
- Preview-strip HTML client-side to mirror the sanitizer and reject empties.
- Keep the comment feature set within the tags the sanitizer allows.
When it happens
Trigger: Posting/replying a comment whose body is only whitespace, only disallowed tags (e.g. `<script>`, `<iframe>`, an unknown tag stripped by the allowlist), or markup whose allowed subset reduces to nothing (e.g. a bare `<br>` with no text). Editing an existing comment to such content also triggers it.
Common situations: A spam bot submits a payload of only disallowed tags; a user pastes only an image/embed that the comment sanitizer strips; a client sends an empty `<p></p>`; the allowlist is tightened in a Ghost version and previously-accepted markup now sanitizes to empty.
Related errors
- Theme is not compatible or contains errors.
- A view with this name already exists
- too_many_files
- invalid_archive
- too_large
AI-assisted analysis of TryGhost/Ghost@47d8b0e2ad (2026-08-13).
Data as JSON: /api/errors/20f738e157c3355d.
Report an issue: GitHub.