Debugging lint-staged failures Jump to heading
When lint-staged fails, the commit stops and the terminal fills with a task list, some ticks, a cross and a block of tool output. Sometimes the cause is obvious — a lint error in your code. Often it is not: a task reports “command not found” though the tool works in your shell, nothing runs at all for a file you clearly staged, the commit is blocked as “empty”, or lint-staged reports a Git error about stashes. Each has a handful of causes, and lint-staged gives you the tools to tell them apart. This page goes through reading the output, reproducing a task by hand, and the fixes for each common failure, within lint-staged formatting automation.
When to use this approach Jump to heading
- A commit fails in the lint-staged hook and the reason is not a lint error in your change.
- lint-staged works for some people on the team and not others.
- Tasks are not running for files you expect them to cover.
- The hook was working and broke after a dependency or tool upgrade.
Step 1 — Read which task failed and why Jump to heading
lint-staged prints each glob, its tasks and their status, then the output of the failed task. Find the cross, then read the tool output beneath it.
✔ Preparing lint-staged...
❯ Running tasks for staged files...
❯ .lintstagedrc.json — 2 files
❯ *.{ts,tsx} — 2 files
✖ eslint --fix [FAILED]
◼ prettier --write
↓ Skipped because of errors from tasks.
✔ Reverting to original state because of errors...
✖ eslint --fix:
/repo/src/billing/totals.ts
14:7 error 'discount' is assigned a value but never used no-unused-vars “Reverting to original state” means your files are exactly as they were before the commit attempt. Nothing was lost.
Step 2 — Reproduce the task by hand Jump to heading
Run the failed command yourself on the same files, from the same directory lint-staged used. If it fails the same way, the problem is the tool or your code; if it succeeds, the problem is the hook environment.
npx lint-staged --debug 2>&1 | grep -E 'cwd|Running|Command' # exact command and directory
cd packages/web && npx eslint --fix src/billing/totals.ts # same command, same place Step 3 — Fix “command not found” and environment differences Jump to heading
When a task works in your shell but fails in the hook, the hook is running with a different environment — common in GUI clients and editors, which do not load shell profiles, and with Node version managers.
# What PATH and Node does the hook see?
printf 'echo "PATH=$PATH"; command -v node; node --version\n' > .husky/pre-commit.debug
sh .husky/pre-commit.debug Run tools through the package manager (npx, pnpm exec) rather than by bare name, so they resolve from node_modules. For Node version managers, Husky can source an init script before every hook; the details are in Husky hooks in GUI clients and IDEs.
Step 4 — Fix tasks that never run Jump to heading
If a staged file is not processed, either no glob matches it or the wrong configuration file was found. Two details cause most of these: globs without a slash match against the file’s base name, while globs with a slash match the path relative to the config file; and in a monorepo, the nearest config wins.
# Which config and which glob does lint-staged pick for each staged file?
npx lint-staged --debug 2>&1 | grep -E 'Found config|Matched|no tasks' // Matches any .ts file at any depth (no slash: base name)
{ "*.ts": "eslint --fix" }
// Matches only .ts files directly in src/ (has a slash: relative path)
{ "src/*.ts": "eslint --fix" }
// Matches .ts files anywhere under src/
{ "src/**/*.ts": "eslint --fix" } Step 5 — Fix empty-commit and stash errors Jump to heading
Two Git-level errors look alarming but have plain causes.
✖ Prevented an empty git commit! The tasks reverted every staged change — usually a formatter undoing a formatting-only change you staged, because your editor and the project’s formatter disagree. Align the editor’s formatter settings with the project’s configuration, or commit with --allow-empty if an empty commit is really intended.
✖ lint-staged failed due to a git error.
Any lost modifications can be restored from a git stash Something went wrong while hiding or restoring unstaged changes. Your work is in the backup stash; recover it as described in handling partially staged files.
git stash list | grep 'lint-staged automatic backup'
git stash apply --index 'stash@{0}' ⚠️ SAFETY WARNING: If lint-staged fails repeatedly with stash errors, do not “fix” it by deleting
.git/index.lockor clearing stashes blindly. A staleindex.lockusually means another Git process is running — an editor, a file watcher — so close it first. Clear stashes only after confirming your work is restored.
Validation checklist Jump to heading
Frequently Asked Questions Jump to heading
Is it safe to commit with --no-verify to get past a broken hook? Jump to heading
As a one-off to save work, yes — CI still checks the code. Fix the hook promptly, though; a hook people routinely bypass protects nothing.
Why does lint-staged say “No staged files match any configured task”? Jump to heading
Either nothing you staged matches a glob — check with --debug — or the configuration was not found because it is in a package directory above none of your files. It is informational, not an error.
Why did the hook pass locally but CI failed on the same files? Jump to heading
Different tool versions or configurations, or CI checking the whole file where lint-staged checked only staged content. Pin tool versions, and run the same configuration in CI with lint-staged --diff.
Related Jump to heading
- Lint-Staged Formatting Automation — the parent topic.
- Speeding Up Slow lint-staged Runs — when the problem is time, not failure.
- Testing Git Hooks Before Sharing Them — catching these issues before teammates do.
- Configuring lint-staged in a Monorepo — where config discovery matters most.