dagger/dagger · error
count lines of added %s: %w
Error message
count lines of added %s: %w
What it means
computeChangesetPathsDelta wraps any failure from countGitLines when counting lines of a newly added file (withStats mode, no rename detection). countGitLines Lstats and reads the added file under afterDir to produce git-numstat-style added line counts, so this error means the added file could not be stat'ed or read at diff time.
Source
Thrown at core/changeset_delta.go:119
if withStats {
stats, err = compareDirectoriesNumStat(ctx, tmpBefore, tmpAfter)
if err != nil {
return nil, nil, fmt.Errorf("numstat delta files: %w", err)
}
}
}
if withStats {
if stats == nil {
stats = make(map[string]lineChanges)
}
if !detectRenames {
// Added/removed files weren't staged for git; their counts are
// just the file's own line count.
for _, rel := range fc.Added {
lines, ok, err := countGitLines(filepath.Join(afterDir, rel))
if err != nil {
return nil, nil, fmt.Errorf("count lines of added %s: %w", rel, err)
}
if ok {
stats[rel] = lineChanges{Added: lines}
}
}
for _, rel := range fc.Removed {
lines, ok, err := countGitLines(filepath.Join(beforeDir, rel))
if err != nil {
return nil, nil, fmt.Errorf("count lines of removed %s: %w", rel, err)
}
if ok {
stats[rel] = lineChanges{Removed: lines}
}
}
}
}
renamedNew := make([]string, 0, len(fc.Renamed))View on GitHub (pinned to 82ba2681db)
Solutions
- Re-run the diff against stable copies of both trees (or re-materialize snapshots) so files do not change mid-walk
- Check permissions/ownership on the added file under afterDir and ensure the process can read it
- Verify the added path exists on disk after the walk; if the tree mutates concurrently, serialize the diff
- If the file is intentionally transient, exclude it from the changeset input before diffing
Example fix
// before: diffing live mutating dirs directly stats, err := computeChangesetPathsDelta(ctx, liveBeforeDir, liveAfterDir, true) // after: snapshot/copy dirs first, then diff beforeCopy, afterCopy := snapshotTrees(liveBeforeDir, liveAfterDir) stats, err := computeChangesetPathsDelta(ctx, beforeCopy, afterCopy, true)
Defensive patterns
Strategy: validation
Validate before calling
for _, rel := range fc.Added {
p := filepath.Join(afterDir, rel)
if fi, err := os.Lstat(p); err != nil || !fi.Mode().IsRegular() {
return fmt.Errorf("added file unreadable before stats: %s: %w", p, err)
}
} Type guard
func fileReadable(root, rel string) bool {
fi, err := os.Lstat(filepath.Join(root, rel))
return err == nil && (fi.Mode().IsRegular() || fi.Mode()&os.ModeSymlink != 0)
} Try / catch
lines, ok, err := countGitLines(p)
if err != nil {
var perr *fs.PathError
if errors.As(err, &perr) && errors.Is(perr.Err, fs.ErrNotExist) {
continue // file vanished mid-diff; skip or retry
}
return fmt.Errorf("count lines of added %s: %w", rel, err)
} Prevention
- Diff immutable snapshots, not live directories
- Don't delete or prune tree contents while a diff runs
- Verify permissions on generated files before diffing
- Retry the whole diff on transient IO errors
When it happens
Trigger: Calling computeChangesetPathsDelta with withStats=true when the after tree contains an added file that disappears or becomes unreadable between the metadata walk and the counting pass (concurrent mutation), the path is a broken/dangling special file, or permission bits deny opening it.
Common situations: Diffing two mounted snapshot directories while a build concurrently rewrites them; a file deleted by a cleanup step mid-diff; a root-only-readable file in a container layer; overlay/whiteout oddities making a path vanish.
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
- count lines of removed %s: %w
- check migration target %q: %w
- failed to read stable ID: %w
- failed to write stable ID: %w
- failed to copy file data for %s
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/6425e2205ea463ff.
Report an issue: GitHub.