Skip to content
Latchkey

pre-commit hook with stages: [manual] never runs in CI

A hook restricted to stages: [manual] only runs when you invoke that stage explicitly. A normal pre-commit run --all-files skips it, so a gate you expected to enforce is silently absent in CI.

What this error means

A hook you configured never appears in the CI output, or a hook you meant to run only manually is executing on every run. The stages value controls this.

pre-commit
# expected the security scan to run in CI, but the log shows only:
black....................................................................Passed
isort....................................................................Passed
# the manual-stage hook was never invoked

Common causes

A required hook is limited to the manual stage

With stages: [manual], the hook is excluded from the default run and only fires when you call the manual stage explicitly.

The CI step does not target the intended stage

CI runs the default stage, so any hook scoped to a different stage is skipped.

How to fix it

Run the hook stage you intend in CI

  1. Decide which stage the hook should run in.
  2. Either broaden its stages or invoke the manual stage in CI.
  3. Confirm the hook now appears in the log.
.github/workflows/ci.yml
- run: pre-commit run --hook-stage manual --all-files

Adjust the stages in the config

Include the stage the CI job runs so the hook is not skipped.

.pre-commit-config.yaml
- id: security-scan
  stages: [pre-commit, manual]

How to prevent it

  • Match each hooks stages` to where you want it enforced.
  • Use --hook-stage manual in CI for manual-only hooks.
  • Audit that every expected hook appears in the CI log.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →