From 9099a030f475bb4436b8e275959082b7e51bcd1d Mon Sep 17 00:00:00 2001 From: "Jonathan A. Sternberg" Date: Wed, 29 Oct 2025 16:08:46 -0500 Subject: [PATCH] dap: attempt to find multiple digests when a failure happens The solve error that gets returned sometimes has a platform when the LLB returned by `ToState` doesn't. In order to ensure we find the failed digest, we now search for both the digest of what was returned and also clear out the platform and search for the digest without that in case that one matches instead. Signed-off-by: Jonathan A. Sternberg --- dap/thread.go | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/dap/thread.go b/dap/thread.go index 47efbe2ba..218a1f1ac 100644 --- a/dap/thread.go +++ b/dap/thread.go @@ -4,6 +4,7 @@ import ( "context" "path" "path/filepath" + "slices" "sync" "github.com/docker/buildx/build" @@ -646,29 +647,38 @@ func (t *thread) rewind(ctx Context, inErr error) (k string, result *step, mount return "", nil, nil, inErr } - dt, err := solveErr.Op.Marshal() - if err != nil { - return "", nil, nil, err + // Find the error digests we might have failed on. + var digests []digest.Digest + if dt, err := solveErr.Op.Marshal(); err == nil { + digests = append(digests, digest.FromBytes(dt)) } - // Find the error digest. - errDgst := digest.FromBytes(dt) + // Include a version of the digest without the platform + // if this is a file op. + if _, ok := solveErr.Op.Op.(*pb.Op_File); ok && solveErr.Op.Platform != nil { + op := solveErr.Op.CloneVT() + op.Platform = nil + + if dt, err := op.Marshal(); err == nil { + digests = append(digests, digest.FromBytes(dt)) + } + } + + if len(digests) == 0 { + return "", nil, nil, inErr + } // Iterate from the first step to find the one we failed on. result = t.entrypoint - for result != nil && result.dgst != errDgst { + for result != nil && !slices.Contains(digests, result.dgst) { result = result.in } - if result == nil { - return "", nil, nil, inErr - } - // Seek to this step. This should succeed because otherwise // we wouldn't have been able to even fail on it to begin with. - k, result, mounts, err = t.seek(ctx, result) - if err != nil { - return k, result, mounts, err + k, result, mounts, retErr = t.seek(ctx, result) + if retErr != nil { + return k, result, mounts, retErr } return k, result, mounts, inErr }