Git hooks that exit with code 1 block the Git operation they're attached to. This typically occurs when pre-commit, pre-push, or other hooks detect issues like linting errors, failing tests, or script problems that prevent the operation from completing.
When you see "hook exited with error code 1", it means a Git hook script ran and returned a non-zero exit code, signaling failure. Git hooks are scripts that run automatically at certain points in the Git workflow - before commits, before pushes, after merges, etc. When a hook returns exit code 1 (or any non-zero value), Git aborts the operation. This is intentional behavior designed to enforce code quality standards. Common hook types that produce this error include: - **pre-commit**: Runs before a commit is created (linting, formatting checks) - **pre-push**: Runs before code is pushed to a remote (tests, build verification) - **commit-msg**: Validates commit message format - **pre-receive**: Server-side hook that can reject pushes The error originates from whatever the hook script is checking - not from Git itself. The hook might be running ESLint, Prettier, unit tests, or custom validation scripts. When any of these checks fail, they exit with code 1 to signal the failure.
The error message usually includes output from the failing hook. Look for specific error details:
# Example output showing ESLint failures
error: pre-commit hook exited with error code 1
> lint-staged
Running tasks for staged files...
ESLint found 3 errors:
src/app.ts:15:1 - 'unused' is defined but never usedThis tells you exactly what to fix - in this case, remove unused variables.
If the hook runs linting or tests, run those commands directly:
# If using npm scripts
npm run lint
npm run test
# If using Husky with lint-staged
npx lint-staged --debug
# Check your package.json for the exact commands
cat package.json | grep -A 5 '"scripts"'This gives you the full error output without the hook wrapper.
Address whatever the hook is complaining about:
# Auto-fix linting issues
npm run lint -- --fix
# Format code with Prettier
npx prettier --write .
# Run tests and fix failures
npm testAfter fixing, stage the changes and retry:
git add .
git commit -m "Fix linting errors"If hooks stopped working after a package update or reinstall:
# Remove existing hooks
rm -rf .git/hooks
# Reinstall project dependencies
rm -rf node_modules
npm install
# For Husky v8+
npx husky install
# For older Husky versions, the postinstall script handles thisGUI Git clients (GitKraken, SourceTree, VS Code) may not have the same PATH as your terminal. They might not find Node.js, npm, or other tools.
For GitKraken:
Preferences > Experimental > Use System Git (instead of bundled Git)
For VS Code:
Ensure Node.js is installed system-wide, not just via nvm without proper shell integration.
Debug by checking PATH:
# Create a test hook
echo '#!/bin/sh
echo $PATH > /tmp/git-hook-path.txt' > .git/hooks/pre-commit
chmod +x .git/hooks/pre-commitCompare the PATH in /tmp/git-hook-path.txt with your terminal's PATH.
If you need to commit or push urgently while troubleshooting:
# Skip pre-commit hooks
git commit --no-verify -m "Emergency fix"
# Skip pre-push hooks
git push --no-verify
# For Husky specifically, you can also use:
HUSKY=0 git commit -m "Skip hooks"
HUSKY=0 git pushWarning: Only use this for emergencies. Skipping hooks bypasses code quality checks that protect your codebase.
Add debugging to understand what's failing:
# Edit the hook script (e.g., .husky/pre-commit)
#!/bin/sh
set -x # Enable command tracing
. "$(dirname "$0")/_/husky.sh"
echo "PATH: $PATH"
echo "PWD: $PWD"
which node
which npm
npx lint-stagedThis prints each command before execution and shows environment details.
If you see errors about git-lfs not being found:
# Check if it's a Git LFS hook
cat .git/hooks/pre-push
# If it references git-lfs and you don't need it:
rm .git/hooks/pre-push
# Or install git-lfs if you do need it
# macOS
brew install git-lfs
# Ubuntu/Debian
apt install git-lfs
# Then initialize
git lfs installUnderstanding hook exit codes: In UNIX systems, exit code 0 means success, and any non-zero value (1-255) means failure. Exit code 1 is the generic error code. Some tools use specific codes (e.g., ESLint uses 1 for lint errors, 2 for fatal errors).
Selectively skipping hooks with pre-commit framework: If using the pre-commit framework (not Husky), you can skip specific hooks:
SKIP=eslint,prettier git commit -m "Skip only certain hooks"Hook execution order: Git runs hooks in a specific order. For commits: pre-commit -> prepare-commit-msg -> commit-msg -> post-commit. If pre-commit fails, the others never run.
Server-side hooks vs client-side hooks: If you're getting "pre-receive hook declined" or "remote rejected", the hook is running on the Git server (GitHub, GitLab, Bitbucket), not locally. You'll need to fix the code or adjust server settings.
Windows troubleshooting: On Windows, ensure hooks have proper shebang lines (#!/bin/sh or #!/bin/bash) and Unix line endings (LF, not CRLF). Git for Windows typically handles this, but issues can occur.
CI/CD considerations: In CI environments, you might want to skip client-side hooks since the CI has its own checks:
# GitHub Actions example
- run: git config --global core.hooksPath /dev/nullkex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server
fatal: unable to access: Proxy auto-configuration failed
How to fix 'Proxy auto-configuration failed' in Git
fatal: unable to access: Authentication failed (proxy requires basic auth)
How to fix 'Authentication failed (proxy requires basic auth)' in Git
fatal: unable to access: no_proxy configuration not working
How to fix 'no_proxy configuration not working' in Git
fatal: unable to read tree object in treeless clone
How to fix 'unable to read tree object in treeless clone' in Git