dagger/dagger · error
compute paths for changeset %d: %w
Error message
compute paths for changeset %d: %w
What it means
During multiway changeset merging, Dagger computes paths for each incoming changeset in parallel jobs and wraps any ComputePaths failure with the index of the offending changeset. The %d identifies which changeset in the 'others' slice failed, so you can pinpoint the bad input.
Source
Thrown at core/changeset.go:1149
func (ch *Changeset) WithChangesets(
ctx context.Context,
others []*Changeset,
onConflictStrategy WithChangesetsMergeConflict,
) (*Changeset, error) {
// Before wasting any effort, remove any changesets that are empty.
//
// This asks ComputePaths rather than IsEmpty: every surviving changeset
// needs its paths computed anyway and ComputePaths memoizes, whereas
// IsEmpty would mount and walk both trees all over again for each one. It
// also counts directory-only changes, which IsEmpty deliberately ignores
// the way `git diff --quiet` does.
filtered := make([]*Changeset, len(others))
jobs := changesetJobs()
for i, other := range others {
jobs = jobs.WithJob(fmt.Sprintf("changeset %d paths", i), func(ctx context.Context) error {
paths, err := other.ComputePaths(ctx)
if err != nil {
return fmt.Errorf("compute paths for changeset %d: %w", i, err)
}
if !changesetPathsEmpty(paths) {
filtered[i] = other
}
return nil
})
}
if err := jobs.Run(ctx); err != nil {
return nil, err
}
others = slices.DeleteFunc(filtered, func(cs *Changeset) bool { return cs == nil })
if len(others) == 0 {
return ch, nil
}
// Single element uses more efficient 2-way merge
if len(others) == 1 {View on GitHub (pinned to 82ba2681db)
Solutions
- Use the %d index to find the failing changeset in your input slice and inspect its wrapped cause.
- Remove or rebuild the offending changeset from valid directories, then retry the merge.
- Pre-validate each changeset by calling ComputePaths individually before the batch merge.
- Retry with a fresh context if the failure was cancellation inside the parallel job.
Example fix
// before: merging an unvalidated batch
merged, err := base.WithChangesets(ctx, allOthers)
// after: validate each changeset's paths first
for i, cs := range allOthers {
if _, err := cs.ComputePaths(ctx); err != nil {
return fmt.Errorf("changeset %d invalid: %w", i, err)
}
}
merged, err := base.WithChangesets(ctx, allOthers) Defensive patterns
Strategy: validation
Validate before calling
for i, cs := range others {
if cs == nil { return fmt.Errorf("changeset %d is nil", i) }
if _, err := cs.ComputePaths(ctx); err != nil {
return fmt.Errorf("changeset %d paths failed: %w", i, err)
}
} Type guard
func allChangesetsValid(others []*dagger.Changeset) bool {
for _, cs := range others { if cs == nil { return false } }
return true
} Try / catch
merged, err := base.WithChangesets(ctx, others)
if err != nil {
var idx int
if _, err := fmt.Sscanf(err.Error(), "compute paths for changeset %d", &idx); err == nil {
return fmt.Errorf("bad input changeset at index %d: %w", idx, err)
}
return err
} Prevention
- Pre-validate every changeset in a batch with ComputePaths before the merge.
- Filter out empty/nil changesets from the input slice.
- Localize errors by keeping batch sizes small and index-annotated.
When it happens
Trigger: Calling the multiway merge (WithChangesets / merge of N changesets) where changeset i's ComputePaths fails - its before/after directories cannot be diffed due to invalid IDs, evaluation errors, or cancellation inside the job.
Common situations: Passing a list of changesets where one was built from a failed step or another engine session; batch merges where a single stale changeset poisons the whole operation.
Related errors
- materialize changes for changeset %d: %w
- compute our paths: %w
- compute their paths: %w
- materialize our changes: %w
- materialize their changes: %w
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/cfcbbe9ced77963b.
Report an issue: GitHub.