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

  1. Add a meta.messages object to the rule that includes the messageId used in the suggestion, e.g. meta: { messages: { foo: 'Replace with bar.' } }.
  2. Verify the suggestion's messageId string exactly matches a key in meta.messages.
  3. 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

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


AI-assisted analysis of eslint/eslint@f131c034ad (2026-08-03). Data as JSON: /data/errors/78f8b02e62e0e68c.json. Report an issue: GitHub.