diff --git a/registry/app/pkg/docker/controller.go b/registry/app/pkg/docker/controller.go index 40febec9cf..bde7ba3832 100644 --- a/registry/app/pkg/docker/controller.go +++ b/registry/app/pkg/docker/controller.go @@ -422,13 +422,13 @@ func (c *Controller) CancelBlobUpload( errors = append(errors, e) return responseHeaders, errors } - defer blobCtx.Upload.Close() responseHeaders = &commons.ResponseHeaders{ Headers: map[string]string{"Docker-Upload-UUID": blobCtx.UUID}, } //nolint:contextcheck + // Note: Cancel() internally closes the writer, so no defer Close() needed if err := blobCtx.Upload.Cancel(blobCtx); err != nil { log.Ctx(ctx).Error().Stack().Err(err).Msgf("error encountered canceling upload: %v", err) errors = append(errors, errcode.ErrCodeUnknown.WithDetail(err)) diff --git a/registry/app/pkg/docker/local.go b/registry/app/pkg/docker/local.go index 3698cab893..5a72ef426e 100644 --- a/registry/app/pkg/docker/local.go +++ b/registry/app/pkg/docker/local.go @@ -1094,7 +1094,13 @@ func (r *LocalRegistry) PushBlob( return responseHeaders, errs } - defer ctx.Upload.Close() + // Track if upload was cancelled to prevent double-close in defer + uploadCancelled := false + defer func() { + if !uploadCancelled { + ctx.Upload.Close() + } + }() if artInfo.Digest == "" { // no digest? return error, but allow retry. @@ -1165,6 +1171,7 @@ func (r *LocalRegistry) PushBlob( } //nolint:contextcheck // Clean up the backend blob data if there was an error. + uploadCancelled = true // Mark as cancelled to prevent defer Close() from running if err := ctx.Upload.Cancel(ctx); err != nil { // If the cleanup fails, all we can do is observe and report. log.Ctx(ctx).Error().Msgf("error canceling upload after error: %v", err)