Skip to content
Latchkey

GitLab CI "rules:exists" Not Matching - Glob or Repo-Root Mismatch

rules:exists runs a job only when matching files are present in the repository. It misfires when the glob does not match nested paths, the case is wrong, or the path is assumed relative to a subdirectory.

What this error means

A job guarded by rules:exists never runs even though the file is in the repo, or always runs because the glob is too broad. The pattern and the repo layout do not line up.

Job rules
# Expected to run when a Dockerfile exists anywhere, but only checks the root:
docker_build:
  rules:
    - exists:
        - Dockerfile        # misses services/api/Dockerfile

Common causes

Glob does not match nested paths

Dockerfile matches only a root-level file. To match at any depth you need **/Dockerfile. A too-narrow pattern makes the rule never match.

Paths are relative to the repo root

rules:exists evaluates from the repository root, not the job’s working directory. Assuming a subdirectory base makes the path wrong.

Case sensitivity

Glob matching is case-sensitive on Linux runners. dockerfile will not match Dockerfile.

How to fix it

Use a recursive, correctly-cased glob

.gitlab-ci.yml
docker_build:
  rules:
    - exists:
        - '**/Dockerfile'
  script: docker build .

Anchor paths at the repo root

  1. Write exists paths relative to the repository root, not the job CWD.
  2. Match exact case as the file is committed.
  3. Use **/ to match the file at any directory depth.

How to prevent it

  • Prefer **/name recursive globs for rules:exists.
  • Remember exists is rooted at the repo, regardless of job CWD.
  • Match committed filename casing exactly on Linux runners.

Related guides

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