dotnet/runtime · error · RuntimeError
Comparison failed for the following files(s)
Error message
Comparison failed for the following files(s): {} What it means
Raised by update_directory() in utilities.py at src/coreclr/scripts/utilities.py:96 when filecmp.cmpfiles reports a non-empty errors list — files present in both source and destination that could not be compared due to an OS-level error (permission denied, file vanished mid-comparison, etc.).
Solutions
- Ensure the process has read access to all common files in srcpath and dstpath.
- Stop concurrent processes that may lock or delete files during the sync.
- Retry — a file may have been transiently locked.
- On Windows, exclude the directories from antivirus on-access scanning.
Defensive patterns
Strategy: retry
Validate before calling
import os, stat
for d in (srcpath, dstpath):
for entry in os.listdir(d):
p = os.path.join(d, entry)
if os.path.isfile(p) and not os.access(p, os.R_OK):
raise SystemExit(f'Unreadable file before sync: {p}') Try / catch
for attempt in range(3):
try:
update_directory(srcpath, dstpath, recursive=True, destructive=True, shallow=False)
break
except RuntimeError as e:
if 'Comparison failed' in str(e) and attempt < 2:
time.sleep(2)
continue
raise Prevention
- Avoid running other processes that touch dstpath during update_directory().
- Run syncs with sufficient file permissions and disable AV on-access scanning on the work tree.
When it happens
Trigger: A file exists in both srcpath and dstpath but cmpfiles fails to read/stat it; locked files on Windows; files deleted by another process during the sync.
Common situations: Antivirus locking files on Windows Helix; a concurrent process writing to dstpath; permission mismatch between source and destination.
Related errors
- Unable to find MinGit asset for arch
- Cannot find System.Private.CoreLib.dll at
- Collection 'smoke_tests' is only available for 'nativeaot'…
- {coreclr_args.mode}
- Could not determine JIT-EE version
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/64e340a84c1c0cbd.
Report an issue: GitHub.
Appendix: source
Thrown at src/coreclr/scripts/utilities.py:96
"""Updates dest directory with files from src directory
Args:
destpath (str): The destination path to sync with the source
srcpath (str): The source path to sync to the destination
recursive(boolean): If True, descend into and update subdirectories (default: True)
destructive(boolean): If True, delete files in the destination which do not exist in the source (default: True)
shallow(boolean): If True, only use os.stat to diff files. Do not examine contents (default: False)
"""
srcfiles, srcdirs = split_entries(os.listdir(srcpath), srcpath)
dstfiles, dstdirs = split_entries(os.listdir(dstpath), dstpath)
# Update files in both src and destination which are different in destination
commonfiles = srcfiles.intersection(dstfiles)
_, mismatches, errors = filecmp.cmpfiles(srcpath, dstpath, commonfiles, shallow=shallow)
if errors:
raise RuntimeError("Comparison failed for the following files(s): {}".format(errors))
for mismatch in mismatches:
shutil.copyfile(os.path.join(srcpath, mismatch), os.path.join(dstpath, mismatch))
# Copy over files from source which do not exist in the destination
for missingfile in srcfiles.difference(dstfiles):
shutil.copyfile(os.path.join(srcpath, missingfile), os.path.join(dstpath, missingfile))
#If destructive, delete files in destination which do not exist in sourc
if destructive:
for deadfile in dstfiles.difference(srcfiles):
print(deadfile)
os.remove(os.path.join(dstpath, deadfile))
for deaddir in dstdirs.difference(srcdirs):
print(deaddir)
shutil.rmtree(os.path.join(dstpath, deaddir))
View on GitHub (pinned to 60108ba66e)