{"record":{"id":"cfcbbe9ced77963b","repo":"dagger/dagger","slug":"compute-paths-for-changeset-d-w","errorCode":null,"errorMessage":"compute paths for changeset %d: %w","messagePattern":"compute paths for changeset (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/changeset.go","lineNumber":1149,"sourceCode":"func (ch *Changeset) WithChangesets(\n\tctx context.Context,\n\tothers []*Changeset,\n\tonConflictStrategy WithChangesetsMergeConflict,\n) (*Changeset, error) {\n\t// Before wasting any effort, remove any changesets that are empty.\n\t//\n\t// This asks ComputePaths rather than IsEmpty: every surviving changeset\n\t// needs its paths computed anyway and ComputePaths memoizes, whereas\n\t// IsEmpty would mount and walk both trees all over again for each one. It\n\t// also counts directory-only changes, which IsEmpty deliberately ignores\n\t// the way `git diff --quiet` does.\n\tfiltered := make([]*Changeset, len(others))\n\tjobs := changesetJobs()\n\tfor i, other := range others {\n\t\tjobs = jobs.WithJob(fmt.Sprintf(\"changeset %d paths\", i), func(ctx context.Context) error {\n\t\t\tpaths, err := other.ComputePaths(ctx)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"compute paths for changeset %d: %w\", i, err)\n\t\t\t}\n\t\t\tif !changesetPathsEmpty(paths) {\n\t\t\t\tfiltered[i] = other\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\t}\n\tif err := jobs.Run(ctx); err != nil {\n\t\treturn nil, err\n\t}\n\tothers = slices.DeleteFunc(filtered, func(cs *Changeset) bool { return cs == nil })\n\n\tif len(others) == 0 {\n\t\treturn ch, nil\n\t}\n\n\t// Single element uses more efficient 2-way merge\n\tif len(others) == 1 {","sourceCodeStart":1131,"sourceCodeEnd":1167,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/core/changeset.go#L1131-L1167","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: merging an unvalidated batch\nmerged, err := base.WithChangesets(ctx, allOthers)\n// after: validate each changeset's paths first\nfor i, cs := range allOthers {\n    if _, err := cs.ComputePaths(ctx); err != nil {\n        return fmt.Errorf(\"changeset %d invalid: %w\", i, err)\n    }\n}\nmerged, err := base.WithChangesets(ctx, allOthers)","handlingStrategy":"validation","validationCode":"for i, cs := range others {\n    if cs == nil { return fmt.Errorf(\"changeset %d is nil\", i) }\n    if _, err := cs.ComputePaths(ctx); err != nil {\n        return fmt.Errorf(\"changeset %d paths failed: %w\", i, err)\n    }\n}","typeGuard":"func allChangesetsValid(others []*dagger.Changeset) bool {\n    for _, cs := range others { if cs == nil { return false } }\n    return true\n}","tryCatchPattern":"merged, err := base.WithChangesets(ctx, others)\nif err != nil {\n    var idx int\n    if _, err := fmt.Sscanf(err.Error(), \"compute paths for changeset %d\", &idx); err == nil {\n        return fmt.Errorf(\"bad input changeset at index %d: %w\", idx, err)\n    }\n    return err\n}","preventionTips":["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."],"tags":["go","dagger","changeset","concurrency","error-wrapping"],"backgroundTag":"dagql-evaluation-failed","analyzedSha":"82ba2681dbe30d3547a1dc50ea495900ab5b6047","analyzedAt":"2026-09-05T07:21:37.930Z","contentChangedAt":"2026-09-05T07:21:37.930Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}