Explain how to install Prettier plugins when they fail to resolve - #8721
Merged
Conversation
Prettier v3 loads plugins with a native ESM import() resolved from its current working directory (the workspace) and ignores NODE_PATH. Plugins installed by a pre-command with the default cwd: root are redirected to /node-deps/node_modules, where Prettier never looks, so the install succeeds but the lint still fails with "Cannot find package '...' imported from noop.js". Add a <LINTER_KEY>_ERROR_PLUGIN_NOT_FOUND common_linter_errors entry to the 4 prettier linters. It detects the ESM resolution failures and points to installing the plugins with cwd: workspace, which keeps plain package names in .prettierrc so the same config still works when running Prettier locally without MegaLinter. Fixes #6980
nvuillam
requested review from
Kurt-von-Laven,
bdovaz and
echoix
as code owners
August 12, 2026 07:20
Contributor
✅
|
Contributor
Contributor
Member
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Fixes #6980
Problem
Installing a Prettier plugin via
*_PRE_COMMANDSappears to succeed (added 3 packages), but the lint still fails:Adding
cwd: root— the resolution that works for stylelint and ESLint — does not help either.Root cause
Prettier v3 resolves plugins declared in
.prettierrcwith a native ESMimport(), from a virtualnoop.jsplaced inprocess.cwd()(src/main/plugins/load-plugin.js):MegaLinter runs linters with
cwd= the workspace, so ESM resolution walks/tmp/lint/node_modules→/tmp/node_modules→/node_modules.Two things then collide:
pre_post_factory.complete_command()rewrites anynpm i…pre-command with the defaultcwd: rootintocd /node-deps && npm i…, so the plugin lands in/node-deps/node_modules.NODE_PATH=/node-deps/node_modules, butNODE_PATHis a CommonJS-only mechanism — ESMimport()ignores it entirely.So
/node-deps/node_modulesis invisible to Prettier, which is why the advice that works for stylelint/ESLint (CJSrequire) is exactly wrong for Prettier.Fix
Documentation only — a
<LINTER_KEY>_ERROR_PLUGIN_NOT_FOUNDcommon_linter_errorsentry on the 4 prettier linters (JSON_,YAML_,JAVASCRIPT_,TYPESCRIPT_PRETTIER). It detects the three ESM resolution failure shapes and surfaces the resolution in the failing log, plus a "Known errors and resolutions" section on the generated doc pages.The recommended resolution installs the plugins in the workspace:
This deliberately keeps plain package names in
.prettierrc, so the very same config keeps working when running Prettier locally without MegaLinter. Referencing plugins by absolute/node-deps/...path also works inside the image, but it breaks local runs, so it is explicitly discouraged in the message rather than offered as an alternative.--no-saveleaves an existingpackage.jsonuntouched, andnode_modulesis already in MegaLinter's default excluded directories.Validation
Run against
ghcr.io/oxsecurity/megalinter-only-json_prettier:betawith a workspace declaring"plugins": ["prettier-plugin-toml"]:Cannot find package 'prettier-plugin-toml' imported from /tmp/lint/noop.js(issue reproduced)cwd: rootadded 3 packagesthen same error (matches the report)cwd: workspaceSuccessfully linted all files without errorsThe new message was rendered in the real image by mounting the updated descriptor over
/megalinter-descriptors/json.megalinter-descriptor.yml.Also checked: the regex matches the 3 real failure strings (
Cannot find package,Cannot find module,Directory import … is not supported) and none of normal Prettier output (Checking formatting...,[warn] file, a genuineSyntaxError); all 132 linters still pass the identifier-prefix validation; the 4 descriptors are prettier-clean.Notes
.claude/rules/descriptors.md, which putscommon_linter_errorswith linter-key-prefixed identifiers in the per-descriptor entry rather than the sharedprettier.megalinter-linter.yml.docs/).complete_command()routenpm i prettier-plugin-*to the workspace instead of/node-deps— but that changes pre-command behaviour for everyone, so it is left out of this documentation-only change.