treeverse / treeverse/dvc

`dvc repro`: dvc.lock records dependency hashes from after cmd finishes, allowing the recorded code↔output linkage to be falsified

Open
#11,058 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
15.9k
Forks
1.3k
PR merge metrics
No merged PRs in 30d

Description

Bug Report

Description

Hello,

I discovered today that with dvc repro of a pipeline the hash sums of a stage's dependency
are calculated and stored after execution. Which lets DVC record a false code <-> output linkage,
if a dependency is changed mid-run.

Reproduce

In a DVC repository place a file e.g. bar.py

from time import sleep

param = 20
sleep(param)

with open("bar_output.txt", "w") as f:
    f.write(f"Bar completed after {param} seconds\n")

and the simple dvc.yaml:

stages:
  bar:
    cmd: python bar.py
    deps:
      - bar.py
    outs:
      - bar_output.txt

Now go through the following steps

(0. dvc init if not initialized yet)

  1. dvc repro
  2. change param in bar.py to something else while file executes
  3. rerun dvc repro after pipeline has finished

The pipeline will not be executed, even though the file has changed. The altered code
is hence linked to the pipeline output of the original code.

Expected

I know that this is sort of an edge case. Nevertheless I personally assumed the hash values were calculated before the stage is executed.

Environment information

OS: CachyOS
Python env: installed with uv
python version: 3.13.12
dvc version: 3.67.1

Output of dvc doctor:

DVC version: 3.67.1 (pip)
-------------------------
Platform: Python 3.13.12 on Linux-7.1.2-3-cachyos-x86_64-with-glibc2.43
Subprojects:
        dvc_data = 3.18.3
        dvc_objects = 5.2.0
        dvc_render = 1.0.2
        dvc_task = 0.40.2
        scmrepo = 3.6.2
Supports:
        azure (adlfs = 2026.5.0, knack = 0.14.0, azure-identity = 1.25.3),
        gdrive (pydrive2 = 1.21.2),
        gs (gcsfs = 2026.6.0),
        hdfs (fsspec = 2026.6.0, pyarrow = 24.0.0),
        http (aiohttp = 3.14.1, aiohttp-retry = 2.9.1),
        https (aiohttp = 3.14.1, aiohttp-retry = 2.9.1),
        oss (ossfs = 2025.5.0),
        s3 (s3fs = 2026.6.0),
        ssh (sshfs = 2025.11.0),
        webdav (webdav4 = 0.11.0),
        webdavs (webdav4 = 0.11.0),
        webhdfs (fsspec = 2026.6.0)
Config:
        Global: /home/tim/.config/dvc
        System: /etc/xdg/dvc
Cache types: reflink, hardlink, symlink
Cache directory: btrfs on /dev/nvme1n1p2
Caches: local
Remotes: None
Workspace directory: btrfs on /dev/nvme1n1p2
Repo: dvc, git
Repo.site_cache_dir: /var/tmp/dvc/repo/9df4aa3c978d01a1af9e0e982551cb0b

Is this a bug or is there a reason for this behavior ?
Thank you for your help and advice on this!

Best
Tim

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the dvc repro entry point and the stage dependency-hash handling that updates dvc.lock; use the reported bar.py and dvc.yaml reproduction to observe when hashes are captured. Done means a dependency changed during execution is detected on the next dvc repro instead of preserving the original output linkage.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data-engineering, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.