Skip to content

check-yaml behaves differently in fast path than in pre-commit (silently accepts unknown YAML tags) #2604

Description

@btschwertfeger

Before submitting

  • I have searched the issue list for similar bug reports.

Summary

check-yaml (from pre-commit/pre-commit-hooks) passes under prek but fails under pre-commit for the same config and the same file, because prek's fast path runs a bundled builtin implementation instead of the pinned hook, and that builtin accepts YAML tags like !reference that the real hook rejects unless --unsafe is set.

MRE:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v5.0.0
    hooks:
    - id: check-yaml
# test.yaml
foo: !reference [.bar, script]
$ git init
...
$ ls -a
.  ..  .git  .pre-commit-config.yaml  test.yaml

$ uvx prek run -a
yaml...............................................................Passed

$ uvx pre-commit run -a
yaml...............................................................Failed
- exit code: 1 could not determine a constructor for the tag '!reference' in
"test.yaml", line 1, column 6

$ PREK_NO_FAST_PATH=1 uvx prek run -a
yaml...............................................................Failed
- exit code: 1 could not determine a constructor for the tag '!reference' in
"test.yaml", line 1, column 6

$ uvx pre-commit --version
pre-commit 4.6.2

$ uvx prek --version
prek 0.4.14

No --unsafe is set in the hook args, so check-yaml should reject the unknown tag, same as pre-commit. PREK_NO_FAST_PATH=1 makes prek behave the same as pre-commit exactly, so I assume the fast path builtin is the cause.

In practice, we have two problems now:

  1. Fast path is on by default and there's no per-hook/per-repo way to turn it off in .pre-commit-config.yaml, so we need to use a global PREK_NO_FAST_PATH env var which. Setting that just for local dev while CI stays on defaults defeats the point of matching CI and local behavior in a corporate setup.
  2. Even at -vvv, the log only says Running hook check-yaml in "fast path", but the average reader or those confronted first time with it, don't know what's happening there. It especially doesn't state that a different (bundled) implementation is being used in place of the pinned one, or that its defaults differ, which makes this divergence very hard to diagnose ans questionable why the hook-repository is installed at all.

Platform

Linux 6.17.0-1032-oem x86_64 GNU/Linux

Version (current: 0.4.14)

0.4.14

.pre-commit-config.yaml

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v5.0.0
    hooks:
    - id: check-yaml

Log file

❯ uvx prek -vvv run -a
2026-08-25T10:14:03.626154Z DEBUG prek: 0.4.14
2026-08-25T10:14:03.626200Z DEBUG Args: ["prek", "-vvv", "run", "-a"]
2026-08-25T10:14:03.628043Z TRACE root: close time.busy=1.80ms time.idle=2.11µs
2026-08-25T10:14:03.628084Z DEBUG Git root: /home/bts/del
2026-08-25T10:14:03.628135Z DEBUG Found workspace root at `/home/bts/del`
2026-08-25T10:14:03.628146Z TRACE Include selectors: ``
2026-08-25T10:14:03.628157Z TRACE Skip selectors: ``
2026-08-25T10:14:03.628246Z DEBUG discover{root="/home/bts/del" config=None refresh=false}: Loaded workspace from cache
2026-08-25T10:14:03.628276Z DEBUG discover{root="/home/bts/del" config=None refresh=false}: Loading project configuration path=.pre-commit-config.yaml
2026-08-25T10:14:03.628492Z TRACE discover{root="/home/bts/del" config=None refresh=false}: close time.busy=303µs time.idle=722ns
2026-08-25T10:14:03.628746Z TRACE Checking lock resource="store" path=/home/bts/.cache/prek/.lock
2026-08-25T10:14:03.628770Z DEBUG Acquired lock resource="store"
2026-08-25T10:14:03.631441Z TRACE No requires-python found in pyproject.toml hook=check-yaml
2026-08-25T10:14:03.631504Z TRACE Released lock path=/home/bts/.cache/prek/.lock
2026-08-25T10:14:03.631522Z DEBUG Hooks going to run: ["check-yaml"]
2026-08-25T10:14:03.631550Z TRACE ls_files{cwd="/home/bts/del"}: Executing `cd /home/bts/del && /usr/bin/git -c core.useBuiltinFSMonitor=false --literal-pathspecs ls-files -z -- /home/bts/del`
2026-08-25T10:14:03.633477Z TRACE ls_files{cwd="/home/bts/del"}: close time.busy=343µs time.idle=1.59ms
2026-08-25T10:14:03.633510Z DEBUG All files in the workspace: 2
2026-08-25T10:14:03.634468Z TRACE Checking lock resource="store" path=/home/bts/.cache/prek/.lock
2026-08-25T10:14:03.634498Z DEBUG Acquired lock resource="store"
2026-08-25T10:14:03.636652Z TRACE Executing `/home/bts/.local/share/uv/python/cpython-3.14.3-linux-x86_64-gnu/bin/python3.14 -I -c import sys, json
info = {
    "version": ".".join(map(str, sys.version_info[:3])),
    "base_exec_prefix": sys.base_exec_prefix,
}
print(json.dumps(info))
`
2026-08-25T10:14:03.663545Z TRACE Released lock path=/home/bts/.cache/prek/.lock
2026-08-25T10:14:03.664159Z TRACE Files for project `.` after filtered: 2
2026-08-25T10:14:03.664183Z DEBUG Running priority group with priority 0: ["check-yaml"]
2026-08-25T10:14:03.664213Z TRACE matching_filenames{hook="check-yaml"}: close time.busy=8.69µs time.idle=1.97µs
2026-08-25T10:14:03.664240Z TRACE Files for hook `check-yaml` after filtering matched=true filenames=2
2026-08-25T10:14:03.664270Z DEBUG run{hook_id=check-yaml language=python}: Running hook `check-yaml` in fast path
2026-08-25T10:14:03.664504Z  INFO run{hook_id=check-yaml language=python}: close time.busy=201µs time.idle=44.9µs
check yaml...............................................................Passed
- hook id: check-yaml
- description: checks yaml files for parseable syntax
- duration: 0.00s

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions