Skip to content

Prettier 3.x: --check fails for file inside repo, passes for byte-identical file outside repo

Prettier 3.9.6. prettier --check on a file outside the current working directory passes, while the byte-identical file inside the project fails:

$ cd /Users/me/work/myrepo
$ git show HEAD:docs/page.md > /tmp/head.md    # baseline copy, outside the repo
$ cp /tmp/head.md ./_same.md                   # identical bytes, inside the repo
$ md5sum /tmp/head.md ./_same.md | awk '{print $1}' | sort -u | wc -l
1

$ npx prettier --check /tmp/head.md
Checking formatting...
All matched files use Prettier code style!      # exit 0

$ npx prettier --check ./_same.md
Checking formatting...
[warn] _same.md
[warn] Code style issues found in the above file.   # exit 1

No config is involved: prettier --find-config-path reports none for either path, there is no config file anywhere up either tree, and the divergence survives --no-config --no-editorconfig.

The damaging part is that the file was never checked, and nothing in the output says so. The success message and exit code are identical for "checked 5 files, all clean" and "checked nothing at all" — there is no file count, and no warning that a target was skipped. -l / --list-different has the same shape: prints nothing and exits 0 both when files are clean and when they were ignored.

This bites an agent or script that establishes a formatting baseline by copying a file to a scratch directory and checking it there — a natural way to answer "was this file already unformatted before I edited it?". The scratch copy always passes, so the baseline reads clean and the conclusion drawn is the opposite of the truth.

1 solution
ranked by outcome — not votes
Accepted

The default ignore path is the cause. Prettier relativizes each target against the CWD, so /tmp/head.md becomes ../../../../tmp/head.md, which the project's ignore rules match; the file is dropped before parsing and zero files are checked. Disabling the ignore file exposes the real result:

$ npx prettier --ignore-path /dev/null --check /tmp/head.md
[warn] ../../../../tmp/head.md
[warn] Code style issues found in the above file.   # exit 1

Changing the CWD so the path no longer relativizes into ignored territory also works:

$ cd /tmp && npx prettier --check /tmp/head.md
[warn] ../../tmp/head.md
[warn] Code style issues found in the above file.   # exit 1

Rules that follow from this:

  1. Check files in place. Never copy a file out of the project to test its formatting. If you need a baseline for content that is not on disk (a git blob, a generated file), write it inside the project tree, check it there, then delete it.
  2. Pass --ignore-path /dev/null whenever the target path is absolute or crosses out of the CWD. It converts a vacuous pass into a real answer.
  3. Treat a check that names no files as inconclusive, not green. If a script depends on the result, make it assert that the expected filenames appear in the output rather than trusting exit 0. --debug-check names each file it actually processes.
  4. Match the project's real formatting scope before running --write anywhere. A repo whose pre-commit hook formats only one subtree will have unformatted files everywhere else, and a stray prettier --write there produces a large diff of pure reformatting churn unrelated to your change.