eslint/eslint · error · TypeError

context.report() called with a suggest option that defines b

Error message

context.report() called with a suggest option that defines both a 'messageId' and an 'desc'. Please only pass one.

What it means

Thrown by validateSuggestions() when a single suggestion object provides BOTH a messageId and a desc property. ESLint allows either a messageId (resolved from meta.messages) or an inline desc string, but not both — providing both is ambiguous and almost always a copy-paste mistake. The error forces the author to pick one.

Source

Thrown at lib/linter/file-report.js:414

	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`",
				);
			}

			if (typeof suggestion.fix !== "function") {
				throw new TypeError(
					`context.report() called with a suggest option without a fix function. See: ${JSON.stringify(suggestion, null, 2)}`,
				);
			}
		});
	}
}

View on GitHub (pinned to f131c034ad)

Solutions

  1. Decide which representation you want and delete the other: keep messageId for centralized messages, or keep desc for one-off inline text.
  2. If migrating to messageId, remove the desc property and ensure meta.messages has the key.
  3. Add an ESLint-level or project-level lint check that suggestion objects use exactly one of messageId/desc.

Example fix

// before
context.report({
  node,
  suggest: [{ messageId: 'useBar', desc: 'Replace with bar', fix(fixer) { return fixer.replaceText(node, 'bar'); } }]
});

// after
context.report({
  node,
  suggest: [{ messageId: 'useBar', fix(fixer) { return fixer.replaceText(node, 'bar'); } }]
});
Defensive patterns

Strategy: validation

Validate before calling

function assertSuggestionHasOneLabel(suggestion) {
  const hasId = Boolean(suggestion.messageId);
  const hasDesc = Boolean(suggestion.desc);
  if (hasId && hasDesc) {
    throw new Error('Suggestion must not define both messageId and desc');
  }
}

Type guard

function hasExactlyOneLabel(s) {
  return Boolean(s.messageId) !== Boolean(s.desc); // XOR
}

Prevention

When it happens

Trigger: context.report({ suggest: [{ messageId: 'useBar', desc: 'Replace with bar', fix }] }) — both messageId and desc present. The check at file-report.js:413 `if (suggestion.desc)` inside the messageId branch throws.

Common situations: Converting a suggestion from inline desc to messageId and forgetting to remove desc; copy-pasting a suggestion template; merging two suggestions incorrectly.

Related errors


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