eslint/eslint · error · TypeError
context.report() called with a suggest option with a message
Error message
context.report() called with a suggest option with a messageId '${messageId}', but no messages were present in the rule metadata. What it means
Thrown by validateSuggestions() in file-report.js when a suggestion passed to context.report({ suggest: [...] }) uses a messageId, but the rule's meta.messages object is undefined or absent. ESLint needs meta.messages to resolve the messageId into human-readable suggestion text; without it the suggestion cannot be rendered. This is a TypeError indicating the rule author forgot to declare messages in the rule's metadata while referencing them in suggestions.
Source
Thrown at lib/linter/file-report.js:402
}
return problem;
}
/**
* Validates that suggestions are properly defined. Throws if an error is detected.
* @param {Array<{ desc?: string, messageId?: string }>} suggest The incoming suggest data.
* @param {Object} messages Object of meta messages for the rule.
* @returns {void}
*/
function validateSuggestions(suggest, messages) {
if (suggest && Array.isArray(suggest)) {
suggest.forEach(suggestion => {
if (suggestion.messageId) {
const { messageId } = suggestion;
if (!messages) {
throw new TypeError(
`context.report() called with a suggest option with a messageId '${messageId}', but no messages were present in the rule metadata.`,
);
}
if (!messages[messageId]) {
throw new TypeError(
`context.report() called with a suggest option with a messageId '${messageId}' which is not present in the 'messages' config: ${JSON.stringify(messages, null, 2)}`,
);
}
if (suggestion.desc) {
throw new TypeError(
"context.report() called with a suggest option that defines both a 'messageId' and an 'desc'. Please only pass one.",
);
}
} else if (!suggestion.desc) {
throw new TypeError(
"context.report() called with a suggest option that doesn't have either a `desc` or `messageId`",View on GitHub (pinned to f131c034ad)
Solutions
- Add a meta.messages object to the rule that includes the messageId used in the suggestion, e.g. meta: { messages: { foo: 'Replace with bar.' } }.
- Verify the suggestion's messageId string exactly matches a key in meta.messages.
- If you do not want to use messageId for the suggestion, use desc instead with an inline string.
Example fix
// before
context.report({
node,
message: 'Use bar',
suggest: [{ messageId: 'useBar', fix(fixer) { return fixer.replaceText(node, 'bar'); } }]
});
// rule meta has no messages
// after
meta: {
messages: { useBar: 'Replace with bar.' }
}
context.report({
node,
suggest: [{ messageId: 'useBar', fix(fixer) { return fixer.replaceText(node, 'bar'); } }]
}); Defensive patterns
Strategy: validation
Validate before calling
function validateSuggestionMessages(rule, suggestions) {
const messages = rule?.meta?.messages;
for (const s of suggestions) {
if (s.messageId && (!messages || !(s.messageId in messages))) {
throw new Error(`Suggestion messageId '${s.messageId}' missing from meta.messages`);
}
}
}
// call before registering the rule Type guard
function ruleHasMessagesForSuggestions(rule) {
const messages = rule?.meta?.messages;
return (
typeof rule === 'object' && rule !== null &&
(!rule.meta || !Array.isArray(rule.create?.({}) && []) || true) &&
(messages === undefined || (typeof messages === 'object' && messages !== null))
);
} Try / catch
try {
context.report({ node, suggest: [{ messageId: 'x', fix }] });
} catch (e) {
if (e instanceof TypeError && /no messages were present/.test(e.message)) {
// fall back to inline desc
context.report({ node, suggest: [{ desc: 'x', fix }] });
} else { throw e; }
} Prevention
- Always define meta.messages alongside any messageId usage in suggestions.
- Write a rule authoring test that asserts every suggestion messageId has a matching meta.messages key.
- Use the eslint-plugin/require-meta rule (from eslint-plugin-eslint-plugin) to enforce suggestion/message metadata.
When it happens
Trigger: A rule calls context.report({ suggest: [{ messageId: 'foo', fix(fixer) {...} }] }) but the rule object has no meta.messages property (or meta is entirely missing). The check at file-report.js:401 `if (!messages)` fires, where messages comes from ruleDefinition?.meta?.messages.
Common situations: Rule authors add suggestions referencing a messageId before adding the corresponding meta.messages block; porting a rule from another linter and forgetting the messages metadata; refactoring that moves messages out of meta accidentally; testing a custom rule in isolation without full metadata.
Related errors
- context.report() called with a suggest option with a message
- context.report() called with a suggest option that defines b
- context.report() called with a suggest option that doesn't h
- context.report() called with a messageId, but no messages we
- context.report() called with a message and a messageId. Plea
AI-assisted analysis of eslint/eslint@f131c034ad (2026-08-03).
Data as JSON: /data/errors/78f8b02e62e0e68c.json.
Report an issue: GitHub.