dagger/dagger · error
verify modified file: %w
Error message
verify modified file: %w
What it means
changesetDeltaIsEmpty wraps errors from modifiedFileDiffers for each metadata-suspect candidate with 'verify modified file'. It means content/mode verification of a specific modified file failed — a stat or readlink error (errors 344–347) bubbled up during the emptiness check.
Source
Thrown at core/changeset_delta.go:334
// (e.g. an added empty dir) don't. Added or removed files prove the changeset
// non-empty regardless of how git would pair them into renames, and
// metadata-suspect files are verified by content with an early exit on the
// first real difference.
func changesetDeltaIsEmpty(ctx context.Context, beforeDir, afterDir string) (bool, error) {
delta, err := collectChangesetDelta(ctx, beforeDir, afterDir)
if err != nil {
return false, fmt.Errorf("collect delta: %w", err)
}
if len(delta.addedFiles) > 0 || len(delta.removedFiles) > 0 {
return false, nil
}
for _, rel := range delta.modifiedCandidates {
if err := ctx.Err(); err != nil {
return false, context.Cause(ctx)
}
changed, err := modifiedFileDiffers(beforeDir, afterDir, rel)
if err != nil {
return false, fmt.Errorf("verify modified file: %w", err)
}
if changed {
return false, nil
}
}
return true, nil
}
// gitFileMode maps a file's mode onto the modes git tracks: symlink, and
// executable vs regular file. Other permission bits are invisible to git.
func gitFileMode(fi os.FileInfo) uint32 {
if fi.Mode()&os.ModeSymlink != 0 {
return 0o120000
}
if fi.Mode()&0o111 != 0 {
return 0o100755
}
return 0o100644View on GitHub (pinned to 82ba2681db)
Solutions
- Read the wrapped error to identify the failing file and fix its cause (permissions, deletion)
- Re-run the check with both trees stable/frozen
- Stop concurrent writers (builds, formatters) during the diff
- If caused by a genuinely missing file, re-materialize the snapshot
Example fix
// before: gofmt -w running while emptiness is checked
exec.Command("gofmt", "-w", dir).Start()
empty, err := changesetDeltaIsEmpty(ctx, beforeDir, afterDir)
// after: format first, then check
exec.Command("gofmt", "-w", dir).Run()
empty, err := changesetDeltaIsEmpty(ctx, beforeDir, afterDir) Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := os.Lstat(filepath.Join(beforeDir, rel)); err != nil {
return fmt.Errorf("candidate before side gone: %w", err)
}
if _, err := os.Lstat(filepath.Join(afterDir, rel)); err != nil {
return fmt.Errorf("candidate after side gone: %w", err)
} Type guard
func verifiable(rootA, rootB, rel string) bool {
_, e1 := os.Lstat(filepath.Join(rootA, rel))
_, e2 := os.Lstat(filepath.Join(rootB, rel))
return e1 == nil && e2 == nil
} Try / catch
empty, err := changesetDeltaIsEmpty(ctx, beforeDir, afterDir)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return false, nil // a candidate changed mid-check: not empty
}
return false, fmt.Errorf("verify modified file: %w", err)
} Prevention
- Stop formatters/builders that touch files during the check
- Unwrap to identify the specific failing file
- Retry once after quiescing writers
- Re-materialize snapshots if files are genuinely missing
When it happens
Trigger: A modified candidate's file vanishes or becomes unreadable between the metadata walk and the content verification loop in changesetDeltaIsEmpty — races with writers mutating either tree mid-check.
Common situations: Editors, build daemons, or codegen touching files while an emptiness check runs; cache layers being evicted; permission changes applied concurrently.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- compute paths: %w
- collect delta: %w
- verify modified files: %w
- stage before delta: %w
- stage after delta: %w
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/45e03ded5dcdbc08.
Report an issue: GitHub.