dagger/dagger · error
collect delta: %w
Error message
collect delta: %w
What it means
computeChangesetPathsDelta wraps any failure of collectChangesetDelta as "collect delta: %w". collectChangesetDelta double-walks both directory trees comparing stat metadata to find added/removed/modified candidates. A failure here means the filesystem walk itself failed (unreadable directory, context cancellation, lstat errors), so no changeset delta can be computed.
Source
Thrown at core/changeset_delta.go:43
// modifiedCandidates are files whose metadata differs; content may still
// be identical (e.g. an mtime-only change), so they must be verified
// before being reported as modified.
modifiedCandidates []string
removedFiles []string
addedDirs []string
removedDirs []string
}
// computeChangesetPathsDelta computes ChangesetPaths by walking filesystem
// metadata and reading content only for files the metadata can't rule out,
// instead of content-diffing both full trees like computeChangesetPaths.
// Rename detection and line counts still come from git, but scoped to the
// changed files only. When withStats is true it also returns per-path
// line-change counts matching `git diff --numstat` semantics.
func computeChangesetPathsDelta(ctx context.Context, beforeDir, afterDir string, withStats bool) (*ChangesetPaths, map[string]lineChanges, error) {
delta, err := collectChangesetDelta(ctx, beforeDir, afterDir)
if err != nil {
return nil, nil, fmt.Errorf("collect delta: %w", err)
}
modified, err := verifyModifiedFiles(ctx, beforeDir, afterDir, delta.modifiedCandidates)
if err != nil {
return nil, nil, fmt.Errorf("verify modified files: %w", err)
}
fc := fileChanges{
Added: delta.addedFiles,
Modified: modified,
Removed: delta.removedFiles,
}
// Renames are always an added/removed pair, so the changed files are the
// complete candidate set; running git over just them yields the same
// pairings as a full-tree diff.
detectRenames := len(delta.addedFiles) > 0 && len(delta.removedFiles) > 0
materializeModified := withStats && len(modified) > 0View on GitHub (pinned to 82ba2681db)
Solutions
- Check the wrapped cause: ENOENT/permission errors point at beforeDir/afterDir paths
- Verify both directories exist and are readable before calling the API
- Extend the context timeout if walking a very large tree
- Ensure nothing deletes or mutates the source dirs concurrently with the delta computation
Example fix
// before
delta, err := computeChangesetPathsDelta(ctx, beforeDir, afterDir, true)
// after
if _, err := os.Stat(beforeDir); err != nil { return fmt.Errorf("beforeDir missing: %w", err) }
if _, err := os.Stat(afterDir); err != nil { return fmt.Errorf("afterDir missing: %w", err) }
delta, err := computeChangesetPathsDelta(ctx, beforeDir, afterDir, true) Defensive patterns
Strategy: validation
Validate before calling
for _, d := range []string{beforeDir, afterDir} {
fi, err := os.Stat(d)
if err != nil { return fmt.Errorf("delta dir %s: %w", d, err) }
if !fi.IsDir() { return fmt.Errorf("%s is not a directory", d) }
} Try / catch
if err != nil {
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) { /* retry with longer budget */ }
return fmt.Errorf("delta collection failed: %w", err)
} Prevention
- Stat both directories before computing the delta
- Keep before/after trees immutable during comparison
- Size the context timeout to tree scale
When it happens
Trigger: Calling computeChangesetPathsDelta (directly or via requireSamePaths/requireSameNumStat) with a beforeDir or afterDir that cannot be walked: path does not exist, permission denied, or context cancelled mid-walk.
Common situations: The before/after scratch directory was cleaned up before the call; a subdirectory changed permissions during traversal; context deadline exceeded on very large trees; path casing/mount mismatch between the two sides.
Related errors
- failed to handle changes
- compute paths: %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/46f79b208beb5090.
Report an issue: GitHub.