Repository: distribution/distribution
Pull request #4040 (2023-09-04 15:57:36)

registry/api: move all errors to "errcode" package, and split "Register" to internal / exported
Move all errors to the errcode package


Patch:
diff --git a/.golangci.yml b/.golangci.yml
index 5931556d..35a903a8 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -10,7 +10,6 @@ linters:
     - unused
     - misspell
     - bodyclose
-    - prealloc
   disable:
     - errcheck
 
diff --git a/errors.go b/errors.go
index 4fbfc852..8e0b788d 100644
--- a/errors.go
+++ b/errors.go
@@ -90,7 +90,7 @@ func (ErrManifestUnverified) Error() string {
 type ErrManifestVerification []error
 
 func (errs ErrManifestVerification) Error() string {
-	parts := make([]string, 0, len(errs))
+	var parts []string
 	for _, err := range errs {
 		parts = append(parts, err.Error())
 	}
diff --git a/registry/api/errcode/register.go b/registry/api/errcode/register.go
index 4674d49c..6030c36a 100644
--- a/registry/api/errcode/register.go
+++ b/registry/api/errcode/register.go
@@ -16,7 +16,7 @@ var (
 var (
 	// ErrorCodeUnknown is a generic error that can be used as a last
 	// resort if there is no situation-specific error message that can be used
-	ErrorCodeUnknown = Register("errcode", ErrorDescriptor{
+	ErrorCodeUnknown = register("errcode", ErrorDescriptor{
 		Value:   "UNKNOWN",
 		Message: "unknown error",
 		Description: `Generic error returned when the error does not have an
@@ -25,7 +25,7 @@ var (
 	})
 
 	// ErrorCodeUnsupported is returned when an operation is not supported.
-	ErrorCodeUnsupported = Register("errcode", ErrorDescriptor{
+	ErrorCodeUnsupported = register("errcode", ErrorDescriptor{
 		Value:   "UNSUPPORTED",
 		Message: "The operation is unsupported.",
 		Description: `The operation was unsupported due to a missing
@@ -35,7 +35,7 @@ var (
 
 	// ErrorCodeUnauthorized is returned if a request requires
 	// authentication.
-	ErrorCodeUnauthorized = Register("errcode", ErrorDescriptor{
+	ErrorCodeUnauthorized = register("errcode", ErrorDescriptor{
 		Value:   "UNAUTHORIZED",
 		Message: "authentication required",
 		Description: `The access controller was unable to authenticate
@@ -47,7 +47,7 @@ var (
 
 	// ErrorCodeDenied is returned if a client does not have sufficient
 	// permission to perform an action.
-	ErrorCodeDenied = Register("errcode", ErrorDescriptor{
+	ErrorCodeDenied = register("errcode", ErrorDescriptor{
 		Value:   "DENIED",
 		Message: "requested access to the resource is denied",
 		Description: `The access controller denied access for the
@@ -57,7 +57,7 @@ var (
 
 	// ErrorCodeUnavailable provides a common error to report unavailability
 	// of a service or endpoint.
-	ErrorCodeUnavailable = Register("errcode", ErrorDescriptor{
+	ErrorCodeUnavailable = register("errcode", ErrorDescriptor{
 		Value:          "UNAVAILABLE",
 		Message:        "service unavailable",
 		Description:    "Returned when a service is not available",
@@ -66,7 +66,7 @@ var (
 
 	// ErrorCodeTooManyRequests is returned if a client attempts too many
 	// times to contact a service endpoint.
-	ErrorCodeTooManyRequests = Register("errcode", ErrorDescriptor{
+	ErrorCodeTooManyRequests = register("errcode", ErrorDescriptor{
 		Value:   "TOOMANYREQUESTS",
 		Message: "too many requests",
 		Description: `Returned when a client attempts to contact a
@@ -75,6 +75,157 @@ var (
 	})
 )
 
+const errGroup = "registry.api.v2"
+
+var (
+	// ErrorCodeDigestInvalid is returned when uploading a blob if the
+	// provided digest does not match the blob contents.
+	ErrorCodeDigestInvalid = register(errGroup, ErrorDescriptor{
+		Value:   "DIGEST_INVALID",
+		Message: "provided digest did not match uploaded content",
+		Description: `When a blob is uploaded, the registry will check that
+		the content matches the digest provided by the client. The error may
+		include a detail structure with the key "digest", including the
+		invalid digest string. This error may also be returned when a manifest
+		includes an invalid layer digest.`,
+		HTTPStatusCode: http.StatusBadRequest,
+	})
+
+	// ErrorCodeSizeInvalid is returned when uploading a blob if the provided
+	ErrorCodeSizeInvalid = register(errGroup, ErrorDescriptor{
+		Value:   "SIZE_INVALID",
+		Message: "provided length did not match content length",
+		Description: `When a layer is uploaded, the provided size will be
+		checked against the uploaded content. If they do not match, this error
+		will be returned.`,
+		HTTPStatusCode: http.StatusBadRequest,
+	})
+
+	// ErrorCodeRangeInvalid is returned when uploading a blob if the provided
+	// content range is invalid.
+	ErrorCodeRangeInvalid = register(errGroup, ErrorDescriptor{
+		Value:   "RANGE_INVALID",
+		Message: "invalid content range",
+		Description: `When a layer is uploaded, the provided range is checked
+		against the uploaded chunk. This error is returned if the range is
+		out of order.`,
+		HTTPStatusCode: http.StatusRequestedRangeNotSatisfiable,
+	})
+
+	// ErrorCodeNameInvalid is returned when the name in the manifest does not
+	// match the provided name.
+	ErrorCodeNameInvalid = register(errGroup, ErrorDescriptor{
+		Value:   "NAME_INVALID",
+		Message: "invalid repository name",
+		Description: `Invalid repository name encountered either during
+		manifest validation or any API operation.`,
+		HTTPStatusCode: http.StatusBadRequest,
+	})
+
+	// ErrorCodeTagInvalid is returned when the tag in the manifest does not
+	// match the provided tag.
+	ErrorCodeTagInvalid = register(errGroup, ErrorDescriptor{
+		Value:   "TAG_INVALID",
+		Message: "manifest tag did not match URI",
+		Description: `During a manifest upload, if the tag in the manifest
+		does not match the uri tag, this error will be returned.`,
+		HTTPStatusCode: http.StatusBadRequest,
+	})
+
+	// ErrorCodeNameUnknown when the repository name is not known.
+	ErrorCodeNameUnknown = register(errGroup, ErrorDescriptor{
+		Value:   "NAME_UNKNOWN",
+		Message: "repository name not known to registry",
+		Description: `This is returned if the name used during an operation is
+		unknown to the registry.`,
+		HTTPStatusCode: http.StatusNotFound,
+	})
+
+	// ErrorCodeManifestUnknown returned when image manifest is unknown.
+	ErrorCodeManifestUnknown = register(errGroup, ErrorDescriptor{
+		Value:   "MANIFEST_UNKNOWN",
+		Message: "manifest unknown",
+		Description: `This error is returned when the manifest, identified by
+		name and tag is unknown to the repository.`,
+		HTTPStatusCode: http.StatusNotFound,
+	})
+
+	// ErrorCodeManifestInvalid returned when an image manifest is invalid,
+	// typically during a PUT operation. This error encompasses all errors
+	// encountered during manifest validation that aren't signature errors.
+	ErrorCodeManifestInvalid = register(errGroup, ErrorDescriptor{
+		Value:   "MANIFEST_INVALID",
+		Message: "manifest invalid",
+		Description: `During upload, manifests undergo several checks ensuring
+		validity. If those checks fail, this error may be returned, unless a
+		more specific error is included. The detail will contain information
+		the failed validation.`,
+		HTTPStatusCode: http.StatusBadRequest,
+	})
+
+	// ErrorCodeManifestUnverified is returned when the manifest fails
+	// signature verification.
+	ErrorCodeManifestUnverified = register(errGroup, ErrorDescriptor{
+		Value:   "MANIFEST_UNVERIFIED",
+		Message: "manifest failed signature verification",
+		Description: `During manifest upload, if the manifest fails signature
+		verification, this error will be returned.`,
+		HTTPStatusCode: http.StatusBadRequest,
+	})
+
+	// ErrorCodeManifestBlobUnknown is returned when a manifest blob is
+	// unknown to the registry.
+	ErrorCodeManifestBlobUnknown = register(errGroup, ErrorDescriptor{
+		Value:   "MANIFEST_BLOB_UNKNOWN",
+		Message: "blob unknown to registry",
+		Description: `This error may be returned when a manifest blob is 
+		unknown to the registry.`,
+		HTTPStatusCode: http.StatusBadRequest,
+	})
+
+	// ErrorCodeBlobUnknown is returned when a blob is unknown to the
+	// registry. This can happen when the manifest references a nonexistent
+	// layer or the result is not found by a blob fetch.
+	ErrorCodeBlobUnknown = register(errGroup, ErrorDescriptor{
+		Value:   "BLOB_UNKNOWN",
+		Message: "blob unknown to registry",
+		Description: `This error may be returned when a blob is unknown to the
+		registry in a specified repository. This can be returned with a
+		standard get or if a manifest references an unknown layer during
+		upload.`,
+		HTTPStatusCode: http.StatusNotFound,
+	})
+
+	// ErrorCodeBlobUploadUnknown is returned when an upload is unknown.
+	ErrorCodeBlobUploadUnknown = register(errGroup, ErrorDescriptor{
+		Value:   "BLOB_UPLOAD_UNKNOWN",
+		Message: "blob upload unknown to registry",
+		Description: `If a blob upload has been cancelled or was never
+		started, this error code may be returned.`,
+		HTTPStatusCode: http.StatusNotFound,
+	})
+
+	// ErrorCodeBlobUploadInvalid is returned when an upload is invalid.
+	ErrorCodeBlobUploadInvalid = register(errGroup, ErrorDescriptor{
+		Value:   "BLOB_UPLOAD_INVALID",
+		Message: "blob upload invalid",
+		Description: `The blob upload encountered an error and can no
+		longer proceed.`,
+		HTTPStatusCode: http.StatusNotFound,
+	})
+
+	// ErrorCodePaginationNumberInvalid is returned when the `n` parameter is
+	// not an integer, or `n` is negative.
+	ErrorCodePaginationNumberInvalid = register(errGroup, ErrorDescriptor{
+		Value:   "PAGINATION_NUMBER_INVALID",
+		Message: "invalid number of results requested",
+		Description: `Returned when the "n" parameter (number of results
+		to return) is not an integer, "n" is negative or "n" is bigger than
+		the maximum allowed.`,
+		HTTPStatusCode: http.StatusBadRequest,
+	})
+)
+
 var (
 	nextCode     = 1000
 	registerLock sync.Mutex
@@ -83,6 +234,12 @@ var (
 // Register will make the passed-in error known to the environment and
 // return a new ErrorCode
 func Register(group string, descriptor ErrorDescriptor) ErrorCode {
+	return register(group, descriptor)
+}
+
+// register will make the passed-in error known to the environment and
+// return a new ErrorCode
+func register(group string, descriptor ErrorDescriptor) ErrorCode {
 	registerLock.Lock()
 	defer registerLock.Unlock()
 
diff --git a/registry/api/v2/descriptors.go b/registry/api/v2/descriptors.go
index d0e9620e..63f51cab 100644
--- a/registry/api/v2/descriptors.go
+++ b/registry/api/v2/descriptors.go
@@ -143,7 +143,7 @@ var (
 			Format:      errorsBody,
 		},
 		ErrorCodes: []errcode.ErrorCode{
-			ErrorCodePaginationNumberInvalid,
+			errcode.ErrorCodePaginationNumberInvalid,
 		},
 	}
 
@@ -164,7 +164,7 @@ var (
 			Format:      errorsBody,
 		},
 		ErrorCodes: []errcode.ErrorCode{
-			ErrorCodeNameUnknown,
+			errcode.ErrorCodeNameUnknown,
 		},
 	}
 
@@ -550,8 +550,8 @@ var routeDescriptors = []RouteDescriptor{
 								Description: "The name or reference was invalid.",
 								StatusCode:  http.StatusBadRequest,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeNameInvalid,
-									ErrorCodeTagInvalid,
+									errcode.ErrorCodeNameInvalid,
+									errcode.ErrorCodeTagInvalid,
 								},
 								Body: BodyDescriptor{
 									ContentType: "application/json",
@@ -609,11 +609,11 @@ var routeDescriptors = []RouteDescriptor{
 									Format:      errorsBody,
 								},
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeNameInvalid,
-									ErrorCodeTagInvalid,
-									ErrorCodeManifestInvalid,
-									ErrorCodeManifestUnverified,
-									ErrorCodeBlobUnknown,
+									errcode.ErrorCodeNameInvalid,
+									errcode.ErrorCodeTagInvalid,
+									errcode.ErrorCodeManifestInvalid,
+									errcode.ErrorCodeManifestUnverified,
+									errcode.ErrorCodeBlobUnknown,
 								},
 							},
 							unauthorizedResponseDescriptor,
@@ -625,7 +625,7 @@ var routeDescriptors = []RouteDescriptor{
 								Description: "One or more layers may be missing during a manifest upload. If so, the missing layers will be enumerated in the error response.",
 								StatusCode:  http.StatusBadRequest,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeBlobUnknown,
+									errcode.ErrorCodeBlobUnknown,
 								},
 								Body: BodyDescriptor{
 									ContentType: "application/json",
@@ -678,8 +678,8 @@ var routeDescriptors = []RouteDescriptor{
 								Description: "The specified `name` or `reference` were invalid and the delete was unable to proceed.",
 								StatusCode:  http.StatusBadRequest,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeNameInvalid,
-									ErrorCodeTagInvalid,
+									errcode.ErrorCodeNameInvalid,
+									errcode.ErrorCodeTagInvalid,
 								},
 								Body: BodyDescriptor{
 									ContentType: "application/json",
@@ -695,8 +695,8 @@ var routeDescriptors = []RouteDescriptor{
 								Description: "The specified `name` or `reference` are unknown to the registry and the delete was unable to proceed. Clients can assume the manifest or tag was already deleted if this response is returned.",
 								StatusCode:  http.StatusNotFound,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeNameUnknown,
-									ErrorCodeManifestUnknown,
+									errcode.ErrorCodeNameUnknown,
+									errcode.ErrorCodeManifestUnknown,
 								},
 								Body: BodyDescriptor{
 									ContentType: "application/json",
@@ -775,8 +775,8 @@ var routeDescriptors = []RouteDescriptor{
 								Description: "There was a problem with the request that needs to be addressed by the client, such as an invalid `name` or `tag`.",
 								StatusCode:  http.StatusBadRequest,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeNameInvalid,
-									ErrorCodeDigestInvalid,
+									errcode.ErrorCodeNameInvalid,
+									errcode.ErrorCodeDigestInvalid,
 								},
 								Body: BodyDescriptor{
 									ContentType: "application/json",
@@ -791,8 +791,8 @@ var routeDescriptors = []RouteDescriptor{
 									Format:      errorsBody,
 								},
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeNameUnknown,
-									ErrorCodeBlobUnknown,
+									errcode.ErrorCodeNameUnknown,
+									errcode.ErrorCodeBlobUnknown,
 								},
 							},
 							unauthorizedResponseDescriptor,
@@ -847,8 +847,8 @@ var routeDescriptors = []RouteDescriptor{
 								Description: "There was a problem with the request that needs to be addressed by the client, such as an invalid `name` or `tag`.",
 								StatusCode:  http.StatusBadRequest,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeNameInvalid,
-									ErrorCodeDigestInvalid,
+									errcode.ErrorCodeNameInvalid,
+									errcode.ErrorCodeDigestInvalid,
 								},
 								Body: BodyDescriptor{
 									ContentType: "application/json",
@@ -858,8 +858,8 @@ var routeDescriptors = []RouteDescriptor{
 							{
 								StatusCode: http.StatusNotFound,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeNameUnknown,
-									ErrorCodeBlobUnknown,
+									errcode.ErrorCodeNameUnknown,
+									errcode.ErrorCodeBlobUnknown,
 								},
 								Body: BodyDescriptor{
 									ContentType: "application/json",
@@ -910,8 +910,8 @@ var routeDescriptors = []RouteDescriptor{
 								Name:       "Invalid Name or Digest",
 								StatusCode: http.StatusBadRequest,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeDigestInvalid,
-									ErrorCodeNameInvalid,
+									errcode.ErrorCodeDigestInvalid,
+									errcode.ErrorCodeNameInvalid,
 								},
 							},
 							{
@@ -922,8 +922,8 @@ var routeDescriptors = []RouteDescriptor{
 									Format:      errorsBody,
 								},
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeNameUnknown,
-									ErrorCodeBlobUnknown,
+									errcode.ErrorCodeNameUnknown,
+									errcode.ErrorCodeBlobUnknown,
 								},
 							},
 							{
@@ -1010,8 +1010,8 @@ var routeDescriptors = []RouteDescriptor{
 								Name:       "Invalid Name or Digest",
 								StatusCode: http.StatusBadRequest,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeDigestInvalid,
-									ErrorCodeNameInvalid,
+									errcode.ErrorCodeDigestInvalid,
+									errcode.ErrorCodeNameInvalid,
 								},
 							},
 							{
@@ -1065,8 +1065,8 @@ var routeDescriptors = []RouteDescriptor{
 								Name:       "Invalid Name or Digest",
 								StatusCode: http.StatusBadRequest,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeDigestInvalid,
-									ErrorCodeNameInvalid,
+									errcode.ErrorCodeDigestInvalid,
+									errcode.ErrorCodeNameInvalid,
 								},
 							},
 							unauthorizedResponseDescriptor,
@@ -1122,8 +1122,8 @@ var routeDescriptors = []RouteDescriptor{
 								Name:       "Invalid Name or Digest",
 								StatusCode: http.StatusBadRequest,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeDigestInvalid,
-									ErrorCodeNameInvalid,
+									errcode.ErrorCodeDigestInvalid,
+									errcode.ErrorCodeNameInvalid,
 								},
 							},
 							{
@@ -1187,9 +1187,9 @@ var routeDescriptors = []RouteDescriptor{
 								Description: "There was an error processing the upload and it must be restarted.",
 								StatusCode:  http.StatusBadRequest,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeDigestInvalid,
-									ErrorCodeNameInvalid,
-									ErrorCodeBlobUploadInvalid,
+									errcode.ErrorCodeDigestInvalid,
+									errcode.ErrorCodeNameInvalid,
+									errcode.ErrorCodeBlobUploadInvalid,
 								},
 								Body: BodyDescriptor{
 									ContentType: "application/json",
@@ -1200,7 +1200,7 @@ var routeDescriptors = []RouteDescriptor{
 								Description: "The upload is unknown to the registry. The upload must be restarted.",
 								StatusCode:  http.StatusNotFound,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeBlobUploadUnknown,
+									errcode.ErrorCodeBlobUploadUnknown,
 								},
 								Body: BodyDescriptor{
 									ContentType: "application/json",
@@ -1262,9 +1262,9 @@ var routeDescriptors = []RouteDescriptor{
 								Description: "There was an error processing the upload and it must be restarted.",
 								StatusCode:  http.StatusBadRequest,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeDigestInvalid,
-									ErrorCodeNameInvalid,
-									ErrorCodeBlobUploadInvalid,
+									errcode.ErrorCodeDigestInvalid,
+									errcode.ErrorCodeNameInvalid,
+									errcode.ErrorCodeBlobUploadInvalid,
 								},
 								Body: BodyDescriptor{
 									ContentType: "application/json",
@@ -1275,7 +1275,7 @@ var routeDescriptors = []RouteDescriptor{
 								Description: "The upload is unknown to the registry. The upload must be restarted.",
 								StatusCode:  http.StatusNotFound,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeBlobUploadUnknown,
+									errcode.ErrorCodeBlobUploadUnknown,
 								},
 								Body: BodyDescriptor{
 									ContentType: "application/json",
@@ -1344,9 +1344,9 @@ var routeDescriptors = []RouteDescriptor{
 								Description: "There was an error processing the upload and it must be restarted.",
 								StatusCode:  http.StatusBadRequest,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeDigestInvalid,
-									ErrorCodeNameInvalid,
-									ErrorCodeBlobUploadInvalid,
+									errcode.ErrorCodeDigestInvalid,
+									errcode.ErrorCodeNameInvalid,
+									errcode.ErrorCodeBlobUploadInvalid,
 								},
 								Body: BodyDescriptor{
 									ContentType: "application/json",
@@ -1357,7 +1357,7 @@ var routeDescriptors = []RouteDescriptor{
 								Description: "The upload is unknown to the registry. The upload must be restarted.",
 								StatusCode:  http.StatusNotFound,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeBlobUploadUnknown,
+									errcode.ErrorCodeBlobUploadUnknown,
 								},
 								Body: BodyDescriptor{
 									ContentType: "application/json",
@@ -1438,9 +1438,9 @@ var routeDescriptors = []RouteDescriptor{
 								Description: "There was an error processing the upload and it must be restarted.",
 								StatusCode:  http.StatusBadRequest,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeDigestInvalid,
-									ErrorCodeNameInvalid,
-									ErrorCodeBlobUploadInvalid,
+									errcode.ErrorCodeDigestInvalid,
+									errcode.ErrorCodeNameInvalid,
+									errcode.ErrorCodeBlobUploadInvalid,
 									errcode.ErrorCodeUnsupported,
 								},
 								Body: BodyDescriptor{
@@ -1452,7 +1452,7 @@ var routeDescriptors = []RouteDescriptor{
 								Description: "The upload is unknown to the registry. The upload must be restarted.",
 								StatusCode:  http.StatusNotFound,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeBlobUploadUnknown,
+									errcode.ErrorCodeBlobUploadUnknown,
 								},
 								Body: BodyDescriptor{
 									ContentType: "application/json",
@@ -1497,8 +1497,8 @@ var routeDescriptors = []RouteDescriptor{
 								Description: "An error was encountered processing the delete. The client may ignore this error.",
 								StatusCode:  http.StatusBadRequest,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeNameInvalid,
-									ErrorCodeBlobUploadInvalid,
+									errcode.ErrorCodeNameInvalid,
+									errcode.ErrorCodeBlobUploadInvalid,
 								},
 								Body: BodyDescriptor{
 									ContentType: "application/json",
@@ -1509,7 +1509,7 @@ var routeDescriptors = []RouteDescriptor{
 								Description: "The upload is unknown to the registry. The client may ignore this error and assume the upload has been deleted.",
 								StatusCode:  http.StatusNotFound,
 								ErrorCodes: []errcode.ErrorCode{
-									ErrorCodeBlobUploadUnknown,
+									errcode.ErrorCodeBlobUploadUnknown,
 								},
 								Body: BodyDescriptor{
 									ContentType: "application/json",
diff --git a/registry/api/v2/errors.go b/registry/api/v2/errors.go
deleted file mode 100644
index dcbabfca..00000000
--- a/registry/api/v2/errors.go
+++ /dev/null
@@ -1,158 +0,0 @@
-package v2
-
-import (
-	"net/http"
-
-	"github.com/distribution/distribution/v3/registry/api/errcode"
-)
-
-const errGroup = "registry.api.v2"
-
-var (
-	// ErrorCodeDigestInvalid is returned when uploading a blob if the
-	// provided digest does not match the blob contents.
-	ErrorCodeDigestInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
-		Value:   "DIGEST_INVALID",
-		Message: "provided digest did not match uploaded content",
-		Description: `When a blob is uploaded, the registry will check that
-		the content matches the digest provided by the client. The error may
-		include a detail structure with the key "digest", including the
-		invalid digest string. This error may also be returned when a manifest
-		includes an invalid layer digest.`,
-		HTTPStatusCode: http.StatusBadRequest,
-	})
-
-	// ErrorCodeSizeInvalid is returned when uploading a blob if the provided
-	ErrorCodeSizeInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
-		Value:   "SIZE_INVALID",
-		Message: "provided length did not match content length",
-		Description: `When a layer is uploaded, the provided size will be
-		checked against the uploaded content. If they do not match, this error
-		will be returned.`,
-		HTTPStatusCode: http.StatusBadRequest,
-	})
-
-	// ErrorCodeRangeInvalid is returned when uploading a blob if the provided
-	// content range is invalid.
-	ErrorCodeRangeInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
-		Value:   "RANGE_INVALID",
-		Message: "invalid content range",
-		Description: `When a layer is uploaded, the provided range is checked
-		against the uploaded chunk. This error is returned if the range is
-		out of order.`,
-		HTTPStatusCode: http.StatusRequestedRangeNotSatisfiable,
-	})
-
-	// ErrorCodeNameInvalid is returned when the name in the manifest does not
-	// match the provided name.
-	ErrorCodeNameInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
-		Value:   "NAME_INVALID",
-		Message: "invalid repository name",
-		Description: `Invalid repository name encountered either during
-		manifest validation or any API operation.`,
-		HTTPStatusCode: http.StatusBadRequest,
-	})
-
-	// ErrorCodeTagInvalid is returned when the tag in the manifest does not
-	// match the provided tag.
-	ErrorCodeTagInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
-		Value:   "TAG_INVALID",
-		Message: "manifest tag did not match URI",
-		Description: `During a manifest upload, if the tag in the manifest
-		does not match the uri tag, this error will be returned.`,
-		HTTPStatusCode: http.StatusBadRequest,
-	})
-
-	// ErrorCodeNameUnknown when the repository name is not known.
-	ErrorCodeNameUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{
-		Value:   "NAME_UNKNOWN",
-		Message: "repository name not known to registry",
-		Description: `This is returned if the name used during an operation is
-		unknown to the registry.`,
-		HTTPStatusCode: http.StatusNotFound,
-	})
-
-	// ErrorCodeManifestUnknown returned when image manifest is unknown.
-	ErrorCodeManifestUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{
-		Value:   "MANIFEST_UNKNOWN",
-		Message: "manifest unknown",
-		Description: `This error is returned when the manifest, identified by
-		name and tag is unknown to the repository.`,
-		HTTPStatusCode: http.StatusNotFound,
-	})
-
-	// ErrorCodeManifestInvalid returned when an image manifest is invalid,
-	// typically during a PUT operation. This error encompasses all errors
-	// encountered during manifest validation that aren't signature errors.
-	ErrorCodeManifestInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
-		Value:   "MANIFEST_INVALID",
-		Message: "manifest invalid",
-		Description: `During upload, manifests undergo several checks ensuring
-		validity. If those checks fail, this error may be returned, unless a
-		more specific error is included. The detail will contain information
-		the failed validation.`,
-		HTTPStatusCode: http.StatusBadRequest,
-	})
-
-	// ErrorCodeManifestUnverified is returned when the manifest fails
-	// signature verification.
-	ErrorCodeManifestUnverified = errcode.Register(errGroup, errcode.ErrorDescriptor{
-		Value:   "MANIFEST_UNVERIFIED",
-		Message: "manifest failed signature verification",
-		Description: `During manifest upload, if the manifest fails signature
-		verification, this error will be returned.`,
-		HTTPStatusCode: http.StatusBadRequest,
-	})
-
-	// ErrorCodeManifestBlobUnknown is returned when a manifest blob is
-	// unknown to the registry.
-	ErrorCodeManifestBlobUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{
-		Value:   "MANIFEST_BLOB_UNKNOWN",
-		Message: "blob unknown to registry",
-		Description: `This error may be returned when a manifest blob is 
-		unknown to the registry.`,
-		HTTPStatusCode: http.StatusBadRequest,
-	})
-
-	// ErrorCodeBlobUnknown is returned when a blob is unknown to the
-	// registry. This can happen when the manifest references a nonexistent
-	// layer or the result is not found by a blob fetch.
-	ErrorCodeBlobUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{
-		Value:   "BLOB_UNKNOWN",
-		Message: "blob unknown to registry",
-		Description: `This error may be returned when a blob is unknown to the
-		registry in a specified repository. This can be returned with a
-		standard get or if a manifest references an unknown layer during
-		upload.`,
-		HTTPStatusCode: http.StatusNotFound,
-	})
-
-	// ErrorCodeBlobUploadUnknown is returned when an upload is unknown.
-	ErrorCodeBlobUploadUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{
-		Value:   "BLOB_UPLOAD_UNKNOWN",
-		Message: "blob upload unknown to registry",
-		Description: `If a blob upload has been cancelled or was never
-		started, this error code may be returned.`,
-		HTTPStatusCode: http.StatusNotFound,
-	})
-
-	// ErrorCodeBlobUploadInvalid is returned when an upload is invalid.
-	ErrorCodeBlobUploadInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
-		Value:   "BLOB_UPLOAD_INVALID",
-		Message: "blob upload invalid",
-		Description: `The blob upload encountered an error and can no
-		longer proceed.`,
-		HTTPStatusCode: http.StatusNotFound,
-	})
-
-	// ErrorCodePaginationNumberInvalid is returned when the `n` parameter is
-	// not an integer, or `n` is negative.
-	ErrorCodePaginationNumberInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
-		Value:   "PAGINATION_NUMBER_INVALID",
-		Message: "invalid number of results requested",
-		Description: `Returned when the "n" parameter (number of results
-		to return) is not an integer, "n" is negative or "n" is bigger than
-		the maximum allowed.`,
-		HTTPStatusCode: http.StatusBadRequest,
-	})
-)
diff --git a/registry/api/v2/errors_deprecated.go b/registry/api/v2/errors_deprecated.go
new file mode 100644
index 00000000..b8ba2b25
--- /dev/null
+++ b/registry/api/v2/errors_deprecated.go
@@ -0,0 +1,86 @@
+package v2
+
+import "github.com/distribution/distribution/v3/registry/api/errcode"
+
+var (
+	// ErrorCodeDigestInvalid is returned when uploading a blob if the
+	// provided digest does not match the blob contents.
+	//
+	// Deprecated: use [errcode.ErrorCodeDigestInvalid].
+	ErrorCodeDigestInvalid = errcode.ErrorCodeDigestInvalid
+
+	// ErrorCodeSizeInvalid is returned when uploading a blob if the provided
+	//
+	// Deprecated: use [errcode.ErrorCodeSizeInvalid].
+	ErrorCodeSizeInvalid = errcode.ErrorCodeSizeInvalid
+
+	// ErrorCodeRangeInvalid is returned when uploading a blob if the provided
+	// content range is invalid.
+	//
+	// Deprecated: use [errcode.ErrorCodeRangeInvalid].
+	ErrorCodeRangeInvalid = errcode.ErrorCodeRangeInvalid
+
+	// ErrorCodeNameInvalid is returned when the name in the manifest does not
+	// match the provided name.
+	//
+	// Deprecated: use [errcode.ErrorCodeNameInvalid].
+	ErrorCodeNameInvalid = errcode.ErrorCodeNameInvalid
+
+	// ErrorCodeTagInvalid is returned when the tag in the manifest does not
+	// match the provided tag.
+	//
+	// Deprecated: use [errcode.ErrorCodeTagInvalid].
+	ErrorCodeTagInvalid = errcode.ErrorCodeTagInvalid
+
+	// ErrorCodeNameUnknown when the repository name is not known.
+	//
+	// Deprecated: use [errcode.ErrorCodeNameUnknown].
+	ErrorCodeNameUnknown = errcode.ErrorCodeNameUnknown
+
+	// ErrorCodeManifestUnknown returned when image manifest is unknown.
+	//
+	// Deprecated: use [errcode.ErrorCodeManifestUnknown].
+	ErrorCodeManifestUnknown = errcode.ErrorCodeManifestUnknown
+
+	// ErrorCodeManifestInvalid returned when an image manifest is invalid,
+	// typically during a PUT operation. This error encompasses all errors
+	// encountered during manifest validation that aren't signature errors.
+	//
+	// Deprecated: use [errcode.ErrorCodeManifestInvalid].
+	ErrorCodeManifestInvalid = errcode.ErrorCodeManifestInvalid
+
+	// ErrorCodeManifestUnverified is returned when the manifest fails
+	// signature verification.
+	//
+	// Deprecated: use [errcode.ErrorCodeManifestUnverified].
+	ErrorCodeManifestUnverified = errcode.ErrorCodeManifestUnverified
+
+	// ErrorCodeManifestBlobUnknown is returned when a manifest blob is
+	// unknown to the registry.
+	//
+	// Deprecated: use [errcode.ErrorCodeManifestBlobUnknown].
+	ErrorCodeManifestBlobUnknown = errcode.ErrorCodeManifestBlobUnknown
+
+	// ErrorCodeBlobUnknown is returned when a blob is unknown to the
+	// registry. This can happen when the manifest references a nonexistent
+	// layer or the result is not found by a blob fetch.
+	//
+	// Deprecated: use [errcode.ErrorCodeBlobUnknown].
+	ErrorCodeBlobUnknown = errcode.ErrorCodeBlobUnknown
+
+	// ErrorCodeBlobUploadUnknown is returned when an upload is unknown.
+	//
+	// Deprecated: use [errcode.ErrorCodeBlobUploadUnknown].
+	ErrorCodeBlobUploadUnknown = errcode.ErrorCodeBlobUploadUnknown
+
+	// ErrorCodeBlobUploadInvalid is returned when an upload is invalid.
+	//
+	// Deprecated: use [errcode.ErrorCodeBlobUploadInvalid].
+	ErrorCodeBlobUploadInvalid = errcode.ErrorCodeBlobUploadInvalid
+
+	// ErrorCodePaginationNumberInvalid is returned when the `n` parameter is
+	// not an integer, or `n` is negative.
+	//
+	// Deprecated: use [errcode.ErrorCodePaginationNumberInvalid].
+	ErrorCodePaginationNumberInvalid = errcode.ErrorCodePaginationNumberInvalid
+)
diff --git a/registry/handlers/app.go b/registry/handlers/app.go
index 7e0b418c..0207227b 100644
--- a/registry/handlers/app.go
+++ b/registry/handlers/app.go
@@ -441,11 +441,6 @@ func (app *App) register(routeName string, dispatch dispatchFunc) {
 // configureEvents prepares the event sink for action.
 func (app *App) configureEvents(configuration *configuration.Configuration) {
 	// Configure all of the endpoint sinks.
-	// NOTE(milosgajdos): we are disabling the linter here as
-	// if an endpoint is disabled we continue with the evaluation
-	// of the next one so we do not know the exact size the slice
-	// should have at the time the iteration starts
-	// nolint:prealloc
 	var sinks []events.Sink
 	for _, endpoint := range configuration.Notifications.Endpoints {
 		if endpoint.Disabled {
@@ -666,9 +661,9 @@ func (app *App) dispatcher(dispatch dispatchFunc) http.Handler {
 
 				switch err := err.(type) {
 				case distribution.ErrRepositoryUnknown:
-					context.Errors = append(context.Errors, v2.ErrorCodeNameUnknown.WithDetail(err))
+					context.Errors = append(context.Errors, errcode.ErrorCodeNameUnknown.WithDetail(err))
 				case distribution.ErrRepositoryNameInvalid:
-					context.Errors = append(context.Errors, v2.ErrorCodeNameInvalid.WithDetail(err))
+					context.Errors = append(context.Errors, errcode.ErrorCodeNameInvalid.WithDetail(err))
 				case errcode.Error:
 					context.Errors = append(context.Errors, err)
 				}
diff --git a/registry/handlers/blob.go b/registry/handlers/blob.go
index ee89a098..4d50754d 100644
--- a/registry/handlers/blob.go
+++ b/registry/handlers/blob.go
@@ -6,7 +6,6 @@ import (
 	"github.com/distribution/distribution/v3"
 	"github.com/distribution/distribution/v3/context"
 	"github.com/distribution/distribution/v3/registry/api/errcode"
-	v2 "github.com/distribution/distribution/v3/registry/api/v2"
 	"github.com/gorilla/handlers"
 	"github.com/opencontainers/go-digest"
 )
@@ -18,12 +17,12 @@ func blobDispatcher(ctx *Context, r *http.Request) http.Handler {
 
 		if err == errDigestNotAvailable {
 			return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-				ctx.Errors = append(ctx.Errors, v2.ErrorCodeDigestInvalid.WithDetail(err))
+				ctx.Errors = append(ctx.Errors, errcode.ErrorCodeDigestInvalid.WithDetail(err))
 			})
 		}
 
 		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-			ctx.Errors = append(ctx.Errors, v2.ErrorCodeDigestInvalid.WithDetail(err))
+			ctx.Errors = append(ctx.Errors, errcode.ErrorCodeDigestInvalid.WithDetail(err))
 		})
 	}
 
@@ -59,7 +58,7 @@ func (bh *blobHandler) GetBlob(w http.ResponseWriter, r *http.Request) {
 	desc, err := blobs.Stat(bh, bh.Digest)
 	if err != nil {
 		if err == distribution.ErrBlobUnknown {
-			bh.Errors = append(bh.Errors, v2.ErrorCodeBlobUnknown.WithDetail(bh.Digest))
+			bh.Errors = append(bh.Errors, errcode.ErrorCodeBlobUnknown.WithDetail(bh.Digest))
 		} else {
 			bh.Errors = append(bh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
 		}
@@ -85,7 +84,7 @@ func (bh *blobHandler) DeleteBlob(w http.ResponseWriter, r *http.Request) {
 			bh.Errors = append(bh.Errors, errcode.ErrorCodeUnsupported)
 			return
 		case distribution.ErrBlobUnknown:
-			bh.Errors = append(bh.Errors, v2.ErrorCodeBlobUnknown)
+			bh.Errors = append(bh.Errors, errcode.ErrorCodeBlobUnknown)
 			return
 		default:
 			bh.Errors = append(bh.Errors, err)
diff --git a/registry/handlers/blobupload.go b/registry/handlers/blobupload.go
index ee7626cb..09c00bb8 100644
--- a/registry/handlers/blobupload.go
+++ b/registry/handlers/blobupload.go
@@ -9,7 +9,6 @@ import (
 	"github.com/distribution/distribution/v3"
 	dcontext "github.com/distribution/distribution/v3/context"
 	"github.com/distribution/distribution/v3/registry/api/errcode"
-	v2 "github.com/distribution/distribution/v3/registry/api/v2"
 	"github.com/distribution/distribution/v3/registry/storage"
 	"github.com/distribution/reference"
 	"github.com/gorilla/handlers"
@@ -110,7 +109,7 @@ func (buh *blobUploadHandler) GetUploadStatus(w http.ResponseWriter, r *http.Req
 		upload, err := blobs.Resume(buh, buh.UUID)
 		if err != nil {
 			if err == distribution.ErrBlobUploadUnknown {
-				buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadUnknown.WithDetail(err))
+				buh.Errors = append(buh.Errors, errcode.ErrorCodeBlobUploadUnknown.WithDetail(err))
 			} else {
 				buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
 			}
@@ -131,7 +130,7 @@ func (buh *blobUploadHandler) GetUploadStatus(w http.ResponseWriter, r *http.Req
 // PatchBlobData writes data to an upload.
 func (buh *blobUploadHandler) PatchBlobData(w http.ResponseWriter, r *http.Request) {
 	if buh.Upload == nil {
-		buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadUnknown)
+		buh.Errors = append(buh.Errors, errcode.ErrorCodeBlobUploadUnknown)
 		return
 	}
 
@@ -151,7 +150,7 @@ func (buh *blobUploadHandler) PatchBlobData(w http.ResponseWriter, r *http.Reque
 			return
 		}
 		if start > end || start != buh.Upload.Size() {
-			buh.Errors = append(buh.Errors, v2.ErrorCodeRangeInvalid)
+			buh.Errors = append(buh.Errors, errcode.ErrorCodeRangeInvalid)
 			return
 		}
 
@@ -161,7 +160,7 @@ func (buh *blobUploadHandler) PatchBlobData(w http.ResponseWriter, r *http.Reque
 			return
 		}
 		if clInt != (end-start)+1 {
-			buh.Errors = append(buh.Errors, v2.ErrorCodeSizeInvalid)
+			buh.Errors = append(buh.Errors, errcode.ErrorCodeSizeInvalid)
 			return
 		}
 	}
@@ -186,7 +185,7 @@ func (buh *blobUploadHandler) PatchBlobData(w http.ResponseWriter, r *http.Reque
 // url of the blob.
 func (buh *blobUploadHandler) PutBlobUploadComplete(w http.ResponseWriter, r *http.Request) {
 	if buh.Upload == nil {
-		buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadUnknown)
+		buh.Errors = append(buh.Errors, errcode.ErrorCodeBlobUploadUnknown)
 		return
 	}
 	defer buh.Upload.Close()
@@ -195,14 +194,14 @@ func (buh *blobUploadHandler) PutBlobUploadComplete(w http.ResponseWriter, r *ht
 
 	if dgstStr == "" {
 		// no digest? return error, but allow retry.
-		buh.Errors = append(buh.Errors, v2.ErrorCodeDigestInvalid.WithDetail("digest missing"))
+		buh.Errors = append(buh.Errors, errcode.ErrorCodeDigestInvalid.WithDetail("digest missing"))
 		return
 	}
 
 	dgst, err := digest.Parse(dgstStr)
 	if err != nil {
 		// no digest? return error, but allow retry.
-		buh.Errors = append(buh.Errors, v2.ErrorCodeDigestInvalid.WithDetail("digest parsing failed"))
+		buh.Errors = append(buh.Errors, errcode.ErrorCodeDigestInvalid.WithDetail("digest parsing failed"))
 		return
 	}
 
@@ -221,7 +220,7 @@ func (buh *blobUploadHandler) PutBlobUploadComplete(w http.ResponseWriter, r *ht
 	if err != nil {
 		switch err := err.(type) {
 		case distribution.ErrBlobInvalidDigest:
-			buh.Errors = append(buh.Errors, v2.ErrorCodeDigestInvalid.WithDetail(err))
+			buh.Errors = append(buh.Errors, errcode.ErrorCodeDigestInvalid.WithDetail(err))
 		case errcode.Error:
 			buh.Errors = append(buh.Errors, err)
 		default:
@@ -231,7 +230,7 @@ func (buh *blobUploadHandler) PutBlobUploadComplete(w http.ResponseWriter, r *ht
 			case distribution.ErrUnsupported:
 				buh.Errors = append(buh.Errors, errcode.ErrorCodeUnsupported)
 			case distribution.ErrBlobInvalidLength, distribution.ErrBlobDigestUnsupported:
-				buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadInvalid.WithDetail(err))
+				buh.Errors = append(buh.Errors, errcode.ErrorCodeBlobUploadInvalid.WithDetail(err))
 			default:
 				dcontext.GetLogger(buh).Errorf("unknown error completing upload: %v", err)
 				buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
@@ -256,7 +255,7 @@ func (buh *blobUploadHandler) PutBlobUploadComplete(w http.ResponseWriter, r *ht
 // CancelBlobUpload cancels an in-progress upload of a blob.
 func (buh *blobUploadHandler) CancelBlobUpload(w http.ResponseWriter, r *http.Request) {
 	if buh.Upload == nil {
-		buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadUnknown)
+		buh.Errors = append(buh.Errors, errcode.ErrorCodeBlobUploadUnknown)
 		return
 	}
 	defer buh.Upload.Close()
@@ -275,7 +274,7 @@ func (buh *blobUploadHandler) ResumeBlobUpload(ctx *Context, r *http.Request) ht
 	if err != nil {
 		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 			dcontext.GetLogger(ctx).Infof("error resolving upload: %v", err)
-			buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadInvalid.WithDetail(err))
+			buh.Errors = append(buh.Errors, errcode.ErrorCodeBlobUploadInvalid.WithDetail(err))
 		})
 	}
 	buh.State = state
@@ -283,14 +282,14 @@ func (buh *blobUploadHandler) ResumeBlobUpload(ctx *Context, r *http.Request) ht
 	if state.Name != ctx.Repository.Named().Name() {
 		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 			dcontext.GetLogger(ctx).Infof("mismatched repository name in upload state: %q != %q", state.Name, buh.Repository.Named().Name())
-			buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadInvalid.WithDetail(err))
+			buh.Errors = append(buh.Errors, errcode.ErrorCodeBlobUploadInvalid.WithDetail(err))
 		})
 	}
 
 	if state.UUID != buh.UUID {
 		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 			dcontext.GetLogger(ctx).Infof("mismatched uuid in upload state: %q != %q", state.UUID, buh.UUID)
-			buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadInvalid.WithDetail(err))
+			buh.Errors = append(buh.Errors, errcode.ErrorCodeBlobUploadInvalid.WithDetail(err))
 		})
 	}
 
@@ -300,7 +299,7 @@ func (buh *blobUploadHandler) ResumeBlobUpload(ctx *Context, r *http.Request) ht
 		dcontext.GetLogger(ctx).Errorf("error resolving upload: %v", err)
 		if err == distribution.ErrBlobUploadUnknown {
 			return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-				buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadUnknown.WithDetail(err))
+				buh.Errors = append(buh.Errors, errcode.ErrorCodeBlobUploadUnknown.WithDetail(err))
 			})
 		}
 
@@ -313,7 +312,7 @@ func (buh *blobUploadHandler) ResumeBlobUpload(ctx *Context, r *http.Request) ht
 	if size := upload.Size(); size != buh.State.Offset {
 		dcontext.GetLogger(ctx).Errorf("upload resumed at wrong offset: %d != %d", size, buh.State.Offset)
 		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-			buh.Errors = append(buh.Errors, v2.ErrorCodeRangeInvalid.WithDetail(err))
+			buh.Errors = append(buh.Errors, errcode.ErrorCodeRangeInvalid.WithDetail(err))
 		})
 	}
 	return nil
diff --git a/registry/handlers/catalog.go b/registry/handlers/catalog.go
index 0e633878..a6a1da0e 100644
--- a/registry/handlers/catalog.go
+++ b/registry/handlers/catalog.go
@@ -9,7 +9,6 @@ import (
 	"strconv"
 
 	"github.com/distribution/distribution/v3/registry/api/errcode"
-	v2 "github.com/distribution/distribution/v3/registry/api/v2"
 	"github.com/distribution/distribution/v3/registry/storage/driver"
 	"github.com/gorilla/handlers"
 )
@@ -47,13 +46,13 @@ func (ch *catalogHandler) GetCatalog(w http.ResponseWriter, r *http.Request) {
 	if n := q.Get("n"); n != "" {
 		parsedMax, err := strconv.Atoi(n)
 		if err != nil || parsedMax < 0 {
-			ch.Errors = append(ch.Errors, v2.ErrorCodePaginationNumberInvalid.WithDetail(map[string]string{"n": n}))
+			ch.Errors = append(ch.Errors, errcode.ErrorCodePaginationNumberInvalid.WithDetail(map[string]string{"n": n}))
 			return
 		}
 
 		// if a client requests more than it's allowed to receive
 		if parsedMax > maximumConfiguredEntries {
-			ch.Errors = append(ch.Errors, v2.ErrorCodePaginationNumberInvalid.WithDetail(map[string]int{"n": parsedMax}))
+			ch.Errors = append(ch.Errors, errcode.ErrorCodePaginationNumberInvalid.WithDetail(map[string]int{"n": parsedMax}))
 			return
 		}
 		entries = parsedMax
diff --git a/registry/handlers/manifests.go b/registry/handlers/manifests.go
index c5e2d064..d7bbab92 100644
--- a/registry/handlers/manifests.go
+++ b/registry/handlers/manifests.go
@@ -13,7 +13,6 @@ import (
 	"github.com/distribution/distribution/v3/manifest/ocischema"
 	"github.com/distribution/distribution/v3/manifest/schema2"
 	"github.com/distribution/distribution/v3/registry/api/errcode"
-	v2 "github.com/distribution/distribution/v3/registry/api/v2"
 	"github.com/distribution/distribution/v3/registry/auth"
 	"github.com/distribution/distribution/v3/registry/storage/driver"
 	"github.com/distribution/reference"
@@ -119,7 +118,7 @@ func (imh *manifestHandler) GetManifest(w http.ResponseWriter, r *http.Request)
 		desc, err := tags.Get(imh, imh.Tag)
 		if err != nil {
 			if _, ok := err.(distribution.ErrTagUnknown); ok {
-				imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err))
+				imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestUnknown.WithDetail(err))
 			} else {
 				imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
 			}
@@ -140,7 +139,7 @@ func (imh *manifestHandler) GetManifest(w http.ResponseWriter, r *http.Request)
 	manifest, err := manifests.Get(imh, imh.Digest, options...)
 	if err != nil {
 		if _, ok := err.(distribution.ErrManifestUnknownRevision); ok {
-			imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err))
+			imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestUnknown.WithDetail(err))
 		} else {
 			imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
 		}
@@ -160,11 +159,11 @@ func (imh *manifestHandler) GetManifest(w http.ResponseWriter, r *http.Request)
 	}
 
 	if manifestType == ociSchema && !supports[ociSchema] {
-		imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithMessage("OCI manifest found, but accept header does not support OCI manifests"))
+		imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestUnknown.WithMessage("OCI manifest found, but accept header does not support OCI manifests"))
 		return
 	}
 	if manifestType == ociImageIndexSchema && !supports[ociImageIndexSchema] {
-		imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithMessage("OCI index found, but accept header does not support OCI indexes"))
+		imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestUnknown.WithMessage("OCI index found, but accept header does not support OCI indexes"))
 		return
 	}
 
@@ -183,14 +182,14 @@ func (imh *manifestHandler) GetManifest(w http.ResponseWriter, r *http.Request)
 		}
 
 		if manifestDigest == "" {
-			imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown)
+			imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestUnknown)
 			return
 		}
 
 		manifest, err = manifests.Get(imh, manifestDigest)
 		if err != nil {
 			if _, ok := err.(distribution.ErrManifestUnknownRevision); ok {
-				imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err))
+				imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestUnknown.WithDetail(err))
 			} else {
 				imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
 			}
@@ -198,7 +197,7 @@ func (imh *manifestHandler) GetManifest(w http.ResponseWriter, r *http.Request)
 		}
 
 		if _, isSchema2 := manifest.(*schema2.DeserializedManifest); isSchema2 && !supports[manifestSchema2] {
-			imh.Errors = append(imh.Errors, v2.ErrorCodeManifestInvalid.WithMessage("Schema 2 manifest not supported by client"))
+			imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestInvalid.WithMessage("Schema 2 manifest not supported by client"))
 			return
 		} else {
 			imh.Digest = manifestDigest
@@ -238,27 +237,27 @@ func (imh *manifestHandler) PutManifest(w http.ResponseWriter, r *http.Request)
 	var jsonBuf bytes.Buffer
 	if err := copyFullPayload(imh, w, r, &jsonBuf, maxManifestBodySize, "image manifest PUT"); err != nil {
 		// copyFullPayload reports the error if necessary
-		imh.Errors = append(imh.Errors, v2.ErrorCodeManifestInvalid.WithDetail(err.Error()))
+		imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestInvalid.WithDetail(err.Error()))
 		return
 	}
 
 	mediaType := r.Header.Get("Content-Type")
 	manifest, desc, err := distribution.UnmarshalManifest(mediaType, jsonBuf.Bytes())
 	if err != nil {
-		imh.Errors = append(imh.Errors, v2.ErrorCodeManifestInvalid.WithDetail(err))
+		imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestInvalid.WithDetail(err))
 		return
 	}
 
 	if imh.Digest != "" {
 		if desc.Digest != imh.Digest {
 			dcontext.GetLogger(imh).Errorf("payload digest does not match: %q != %q", desc.Digest, imh.Digest)
-			imh.Errors = append(imh.Errors, v2.ErrorCodeDigestInvalid)
+			imh.Errors = append(imh.Errors, errcode.ErrorCodeDigestInvalid)
 			return
 		}
 	} else if imh.Tag != "" {
 		imh.Digest = desc.Digest
 	} else {
-		imh.Errors = append(imh.Errors, v2.ErrorCodeTagInvalid.WithDetail("no tag or digest specified"))
+		imh.Errors = append(imh.Errors, errcode.ErrorCodeTagInvalid.WithDetail("no tag or digest specified"))
 		return
 	}
 
@@ -297,14 +296,14 @@ func (imh *manifestHandler) PutManifest(w http.ResponseWriter, r *http.Request)
 			for _, verificationError := range err {
 				switch verificationError := verificationError.(type) {
 				case distribution.ErrManifestBlobUnknown:
-					imh.Errors = append(imh.Errors, v2.ErrorCodeManifestBlobUnknown.WithDetail(verificationError.Digest))
+					imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestBlobUnknown.WithDetail(verificationError.Digest))
 				case distribution.ErrManifestNameInvalid:
-					imh.Errors = append(imh.Errors, v2.ErrorCodeNameInvalid.WithDetail(err))
+					imh.Errors = append(imh.Errors, errcode.ErrorCodeNameInvalid.WithDetail(err))
 				case distribution.ErrManifestUnverified:
-					imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnverified)
+					imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestUnverified)
 				default:
 					if verificationError == digest.ErrDigestInvalidFormat {
-						imh.Errors = append(imh.Errors, v2.ErrorCodeDigestInvalid)
+						imh.Errors = append(imh.Errors, errcode.ErrorCodeDigestInvalid)
 					} else {
 						imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown, verificationError)
 					}
@@ -434,7 +433,7 @@ func (imh *manifestHandler) DeleteManifest(w http.ResponseWriter, r *http.Reques
 		if err := tagService.Untag(imh.Context, imh.Tag); err != nil {
 			switch err.(type) {
 			case distribution.ErrTagUnknown, driver.PathNotFoundError:
-				imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err))
+				imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestUnknown.WithDetail(err))
 			default:
 				imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
 			}
@@ -455,10 +454,10 @@ func (imh *manifestHandler) DeleteManifest(w http.ResponseWriter, r *http.Reques
 		switch err {
 		case digest.ErrDigestUnsupported:
 		case digest.ErrDigestInvalidFormat:
-			imh.Errors = append(imh.Errors, v2.ErrorCodeDigestInvalid)
+			imh.Errors = append(imh.Errors, errcode.ErrorCodeDigestInvalid)
 			return
 		case distribution.ErrBlobUnknown:
-			imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown)
+			imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestUnknown)
 			return
 		case distribution.ErrUnsupported:
 			imh.Errors = append(imh.Errors, errcode.ErrorCodeUnsupported)
diff --git a/registry/handlers/tags.go b/registry/handlers/tags.go
index 035b326f..ec0eb233 100644
--- a/registry/handlers/tags.go
+++ b/registry/handlers/tags.go
@@ -8,7 +8,6 @@ import (
 
 	"github.com/distribution/distribution/v3"
 	"github.com/distribution/distribution/v3/registry/api/errcode"
-	v2 "github.com/distribution/distribution/v3/registry/api/v2"
 	"github.com/gorilla/handlers"
 )
 
@@ -42,7 +41,7 @@ func (th *tagsHandler) GetTags(w http.ResponseWriter, r *http.Request) {
 	if err != nil {
 		switch err := err.(type) {
 		case distribution.ErrRepositoryUnknown:
-			th.Errors = append(th.Errors, v2.ErrorCodeNameUnknown.WithDetail(map[string]string{"name": th.Repository.Named().Name()}))
+			th.Errors = append(th.Errors, errcode.ErrorCodeNameUnknown.WithDetail(map[string]string{"name": th.Repository.Named().Name()}))
 		case errcode.Error:
 			th.Errors = append(th.Errors, err)
 		default:
@@ -71,7 +70,7 @@ func (th *tagsHandler) GetTags(w http.ResponseWriter, r *http.Request) {
 	if n := q.Get("n"); n != "" {
 		maxEntries, err := strconv.Atoi(n)
 		if err != nil || maxEntries < 0 {
-			th.Errors = append(th.Errors, v2.ErrorCodePaginationNumberInvalid.WithDetail(map[string]string{"n": n}))
+			th.Errors = append(th.Errors, errcode.ErrorCodePaginationNumberInvalid.WithDetail(map[string]string{"n": n}))
 			return
 		}
 
diff --git a/registry/storage/driver/azure/azure.go b/registry/storage/driver/azure/azure.go
index 3e3c05ce..c2cf9277 100644
--- a/registry/storage/driver/azure/azure.go
+++ b/registry/storage/driver/azure/azure.go
@@ -416,7 +416,7 @@ func directDescendants(blobs []string, prefix string) []string {
 		}
 	}
 
-	keys := make([]string, 0, len(out))
+	var keys []string
 	for k := range out {
 		keys = append(keys, k)
 	}
diff --git a/registry/storage/driver/inmemory/mfs.go b/registry/storage/driver/inmemory/mfs.go
index f3837c5f..da0c2abb 100644
--- a/registry/storage/driver/inmemory/mfs.go
+++ b/registry/storage/driver/inmemory/mfs.go
@@ -97,12 +97,8 @@ func (d *dir) list(p string) ([]string, error) {
 		return nil, errIsNotDir
 	}
 
-	// NOTE(milosgajdos): this is safe to do because
-	// n can only be *dir due to the compile time check
-	dirChildren := n.(*dir).children
-
-	children := make([]string, 0, len(dirChildren))
-	for _, child := range dirChildren {
+	var children []string
+	for _, child := range n.(*dir).children {
 		children = append(children, child.path())
 	}
 
diff --git a/registry/storage/driver/s3-aws/s3.go b/registry/storage/driver/s3-aws/s3.go
index 3df5e5b3..46ee8a18 100644
--- a/registry/storage/driver/s3-aws/s3.go
+++ b/registry/storage/driver/s3-aws/s3.go
@@ -608,7 +608,7 @@ func (d *driver) GetContent(ctx context.Context, path string) ([]byte, error) {
 
 // PutContent stores the []byte content at a location designated by "path".
 func (d *driver) PutContent(ctx context.Context, path string, contents []byte) error {
-	_, err := d.S3.PutObjectWithContext(ctx, &s3.PutObjectInput{
+	_, err := d.S3.PutObject(&s3.PutObjectInput{
 		Bucket:               aws.String(d.Bucket),
 		Key:                  aws.String(d.s3Path(path)),
 		ContentType:          d.getContentType(),
@@ -624,7 +624,7 @@ func (d *driver) PutContent(ctx context.Context, path string, contents []byte) e
 // Reader retrieves an io.ReadCloser for the content stored at "path" with a
 // given byte offset.
 func (d *driver) Reader(ctx context.Context, path string, offset int64) (io.ReadCloser, error) {
-	resp, err := d.S3.GetObjectWithContext(ctx, &s3.GetObjectInput{
+	resp, err := d.S3.GetObject(&s3.GetObjectInput{
 		Bucket: aws.String(d.Bucket),
 		Key:    aws.String(d.s3Path(path)),
 		Range:  aws.String("bytes=" + strconv.FormatInt(offset, 10) + "-"),
@@ -645,7 +645,7 @@ func (d *driver) Writer(ctx context.Context, path string, appendParam bool) (sto
 	key := d.s3Path(path)
 	if !appendParam {
 		// TODO (brianbland): cancel other uploads at this path
-		resp, err := d.S3.CreateMultipartUploadWithContext(ctx, &s3.CreateMultipartUploadInput{
+		resp, err := d.S3.CreateMultipartUpload(&s3.CreateMultipartUploadInput{
 			Bucket:               aws.String(d.Bucket),
 			Key:                  aws.String(key),
 			ContentType:          d.getContentType(),
@@ -665,7 +665,7 @@ func (d *driver) Writer(ctx context.Context, path string, appendParam bool) (sto
 		Prefix: aws.String(key),
 	}
 	for {
-		resp, err := d.S3.ListMultipartUploadsWithContext(ctx, listMultipartUploadsInput)
+		resp, err := d.S3.ListMultipartUploads(listMultipartUploadsInput)
 		if err != nil {
 			return nil, parseError(path, err)
 		}
@@ -683,7 +683,7 @@ func (d *driver) Writer(ctx context.Context, path string, appendParam bool) (sto
 				continue
 			}
 
-			partsList, err := d.S3.ListPartsWithContext(ctx, &s3.ListPartsInput{
+			partsList, err := d.S3.ListParts(&s3.ListPartsInput{
 				Bucket:   aws.String(d.Bucket),
 				Key:      aws.String(key),
 				UploadId: multi.UploadId,
@@ -693,7 +693,7 @@ func (d *driver) Writer(ctx context.Context, path string, appendParam bool) (sto
 			}
 			allParts = append(allParts, partsList.Parts...)
 			for *partsList.IsTruncated {
-				partsList, err = d.S3.ListPartsWithContext(ctx, &s3.ListPartsInput{
+				partsList, err = d.S3.ListParts(&s3.ListPartsInput{
 					Bucket:           aws.String(d.Bucket),
 					Key:              aws.String(key),
 					UploadId:         multi.UploadId,
@@ -722,7 +722,7 @@ func (d *driver) Writer(ctx context.Context, path string, appendParam bool) (sto
 // Stat retrieves the FileInfo for the given path, including the current size
 // in bytes and the creation time.
 func (d *driver) Stat(ctx context.Context, path string) (storagedriver.FileInfo, error) {
-	resp, err := d.S3.ListObjectsV2WithContext(ctx, &s3.ListObjectsV2Input{
+	resp, err := d.S3.ListObjectsV2(&s3.ListObjectsV2Input{
 		Bucket:  aws.String(d.Bucket),
 		Prefix:  aws.String(d.s3Path(path)),
 		MaxKeys: aws.Int64(1),
@@ -767,7 +767,7 @@ func (d *driver) List(ctx context.Context, opath string) ([]string, error) {
 		prefix = "/"
 	}
 
-	resp, err := d.S3.ListObjectsV2WithContext(ctx, &s3.ListObjectsV2Input{
+	resp, err := d.S3.ListObjectsV2(&s3.ListObjectsV2Input{
 		Bucket:    aws.String(d.Bucket),
 		Prefix:    aws.String(d.s3Path(path)),
 		Delimiter: aws.String("/"),
@@ -791,7 +791,7 @@ func (d *driver) List(ctx context.Context, opath string) ([]string, error) {
 		}
 
 		if *resp.IsTruncated {
-			resp, err = d.S3.ListObjectsV2WithContext(ctx, &s3.ListObjectsV2Input{
+			resp, err = d.S3.ListObjectsV2(&s3.ListObjectsV2Input{
 				Bucket:            aws.String(d.Bucket),
 				Prefix:            aws.String(d.s3Path(path)),
 				Delimiter:         aws.String("/"),
@@ -841,7 +841,7 @@ func (d *driver) copy(ctx context.Context, sourcePath string, destPath string) e
 	}
 
 	if fileInfo.Size() <= d.MultipartCopyThresholdSize {
-		_, err := d.S3.CopyObjectWithContext(ctx, &s3.CopyObjectInput{
+		_, err := d.S3.CopyObject(&s3.CopyObjectInput{
 			Bucket:               aws.String(d.Bucket),
 			Key:                  aws.String(d.s3Path(destPath)),
 			ContentType:          d.getContentType(),
@@ -857,7 +857,7 @@ func (d *driver) copy(ctx context.Context, sourcePath string, destPath string) e
 		return nil
 	}
 
-	createResp, err := d.S3.CreateMultipartUploadWithContext(ctx, &s3.CreateMultipartUploadInput{
+	createResp, err := d.S3.CreateMultipartUpload(&s3.CreateMultipartUploadInput{
 		Bucket:               aws.String(d.Bucket),
 		Key:                  aws.String(d.s3Path(destPath)),
 		ContentType:          d.getContentType(),
@@ -884,7 +884,7 @@ func (d *driver) copy(ctx context.Context, sourcePath string, destPath string) e
 			if lastByte >= fileInfo.Size() {
 				lastByte = fileInfo.Size() - 1
 			}
-			uploadResp, err := d.S3.UploadPartCopyWithContext(ctx, &s3.UploadPartCopyInput{
+			uploadResp, err := d.S3.UploadPartCopy(&s3.UploadPartCopyInput{
 				Bucket:          aws.String(d.Bucket),
 				CopySource:      aws.String(d.Bucket + "/" + d.s3Path(sourcePath)),
 				Key:             aws.String(d.s3Path(destPath)),
@@ -910,7 +910,7 @@ func (d *driver) copy(ctx context.Context, sourcePath string, destPath string) e
 		}
 	}
 
-	_, err = d.S3.CompleteMultipartUploadWithContext(ctx, &s3.CompleteMultipartUploadInput{
+	_, err = d.S3.CompleteMultipartUpload(&s3.CompleteMultipartUploadInput{
 		Bucket:          aws.String(d.Bucket),
 		Key:             aws.String(d.s3Path(destPath)),
 		UploadId:        createResp.UploadId,
@@ -931,7 +931,7 @@ func (d *driver) Delete(ctx context.Context, path string) error {
 
 	for {
 		// list all the objects
-		resp, err := d.S3.ListObjectsV2WithContext(ctx, listObjectsInput)
+		resp, err := d.S3.ListObjectsV2(listObjectsInput)
 
 		// resp.Contents can only be empty on the first call
 		// if there were no more results to return after the first call, resp.IsTruncated would have been false
@@ -956,7 +956,7 @@ func (d *driver) Delete(ctx context.Context, path string) error {
 			// by default the response returns up to 1,000 key names. The response _might_ contain fewer keys but it will never contain more.
 			// 10000 keys is coincidentally (?) also the max number of keys that can be deleted in a single Delete operation, so we'll just smack
 			// Delete here straight away and reset the object slice when successful.
-			resp, err := d.S3.DeleteObjectsWithContext(ctx, &s3.DeleteObjectsInput{
+			resp, err := d.S3.DeleteObjects(&s3.DeleteObjectsInput{
 				Bucket: aws.String(d.Bucket),
 				Delete: &s3.Delete{
 					Objects: s3Objects,
@@ -1456,7 +1456,7 @@ func (w *writer) Commit() error {
 	}
 	w.committed = true
 
-	completedUploadedParts := make(completedParts, 0, len(w.parts))
+	var completedUploadedParts completedParts
 	for _, part := range w.parts {
 		completedUploadedParts = append(completedUploadedParts, &s3.CompletedPart{
 			ETag:       part.ETag,
diff --git a/registry/storage/tagstore.go b/registry/storage/tagstore.go
index 268c21cc..bf6541f9 100644
--- a/registry/storage/tagstore.go
+++ b/registry/storage/tagstore.go
@@ -24,24 +24,25 @@ type tagStore struct {
 
 // All returns all tags
 func (ts *tagStore) All(ctx context.Context) ([]string, error) {
+	var tags []string
+
 	pathSpec, err := pathFor(manifestTagPathSpec{
 		name: ts.repository.Named().Name(),
 	})
 	if err != nil {
-		return nil, err
+		return tags, err
 	}
 
 	entries, err := ts.blobStore.driver.List(ctx, pathSpec)
 	if err != nil {
 		switch err := err.(type) {
 		case storagedriver.PathNotFoundError:
-			return nil, distribution.ErrRepositoryUnknown{Name: ts.repository.Named().Name()}
+			return tags, distribution.ErrRepositoryUnknown{Name: ts.repository.Named().Name()}
 		default:
-			return nil, err
+			return tags, err
 		}
 	}
 
-	tags := make([]string, 0, len(entries))
 	for _, entry := range entries {
 		_, filename := path.Split(entry)
 		tags = append(tags, filename)


Test patch:
diff --git a/registry/api/errcode/errors_test.go b/registry/api/errcode/errors_test.go
index 105d9f7c..dacdb6a2 100644
--- a/registry/api/errcode/errors_test.go
+++ b/registry/api/errcode/errors_test.go
@@ -10,21 +10,21 @@ import (
 
 // TestErrorsManagement does a quick check of the Errors type to ensure that
 // members are properly pushed and marshaled.
-var ErrorCodeTest1 = Register("test.errors", ErrorDescriptor{
+var ErrorCodeTest1 = register("test.errors", ErrorDescriptor{
 	Value:          "TEST1",
 	Message:        "test error 1",
 	Description:    `Just a test message #1.`,
 	HTTPStatusCode: http.StatusInternalServerError,
 })
 
-var ErrorCodeTest2 = Register("test.errors", ErrorDescriptor{
+var ErrorCodeTest2 = register("test.errors", ErrorDescriptor{
 	Value:          "TEST2",
 	Message:        "test error 2",
 	Description:    `Just a test message #2.`,
 	HTTPStatusCode: http.StatusNotFound,
 })
 
-var ErrorCodeTest3 = Register("test.errors", ErrorDescriptor{
+var ErrorCodeTest3 = register("test.errors", ErrorDescriptor{
 	Value:          "TEST3",
 	Message:        "Sorry %q isn't valid",
 	Description:    `Just a test message #3.`,
diff --git a/registry/client/blob_writer_test.go b/registry/client/blob_writer_test.go
index d9947aae..134c3e05 100644
--- a/registry/client/blob_writer_test.go
+++ b/registry/client/blob_writer_test.go
@@ -9,7 +9,6 @@ import (
 
 	"github.com/distribution/distribution/v3"
 	"github.com/distribution/distribution/v3/registry/api/errcode"
-	v2 "github.com/distribution/distribution/v3/registry/api/v2"
 	"github.com/distribution/distribution/v3/testutil"
 )
 
@@ -175,8 +174,8 @@ func TestUploadReadFrom(t *testing.T) {
 		if !ok {
 			t.Fatalf("Not an 'Error' type: %#v", uploadErr[0])
 		}
-		if v2Err.Code != v2.ErrorCodeBlobUploadInvalid {
-			t.Fatalf("Unexpected error code: %s, expected %d", v2Err.Code.String(), v2.ErrorCodeBlobUploadInvalid)
+		if v2Err.Code != errcode.ErrorCodeBlobUploadInvalid {
+			t.Fatalf("Unexpected error code: %s, expected %d", v2Err.Code.String(), errcode.ErrorCodeBlobUploadInvalid)
 		}
 		if expected := "blob upload invalid"; v2Err.Message != expected {
 			t.Fatalf("Unexpected error message: %q, expected %q", v2Err.Message, expected)
@@ -463,8 +462,8 @@ func TestUploadWrite(t *testing.T) {
 		if !ok {
 			t.Fatalf("Not an 'Error' type: %#v", uploadErr[0])
 		}
-		if v2Err.Code != v2.ErrorCodeBlobUploadInvalid {
-			t.Fatalf("Unexpected error code: %s, expected %d", v2Err.Code.String(), v2.ErrorCodeBlobUploadInvalid)
+		if v2Err.Code != errcode.ErrorCodeBlobUploadInvalid {
+			t.Fatalf("Unexpected error code: %s, expected %d", v2Err.Code.String(), errcode.ErrorCodeBlobUploadInvalid)
 		}
 		if expected := "blob upload invalid"; v2Err.Message != expected {
 			t.Fatalf("Unexpected error message: %q, expected %q", v2Err.Message, expected)
diff --git a/registry/client/repository_test.go b/registry/client/repository_test.go
index 4cda067a..fee5bd17 100644
--- a/registry/client/repository_test.go
+++ b/registry/client/repository_test.go
@@ -21,7 +21,6 @@ import (
 	"github.com/distribution/distribution/v3/manifest"
 	"github.com/distribution/distribution/v3/manifest/ocischema"
 	"github.com/distribution/distribution/v3/registry/api/errcode"
-	v2 "github.com/distribution/distribution/v3/registry/api/v2"
 	"github.com/distribution/distribution/v3/testutil"
 	"github.com/distribution/distribution/v3/uuid"
 	"github.com/distribution/reference"
@@ -1440,7 +1439,7 @@ func TestObtainsErrorForMissingTag(t *testing.T) {
 
 	var m testutil.RequestResponseMap
 	var errors errcode.Errors
-	errors = append(errors, v2.ErrorCodeManifestUnknown.WithDetail("unknown manifest"))
+	errors = append(errors, errcode.ErrorCodeManifestUnknown.WithDetail("unknown manifest"))
 	errBytes, err := json.Marshal(errors)
 	if err != nil {
 		t.Fatal(err)
diff --git a/registry/handlers/api_test.go b/registry/handlers/api_test.go
index c921ce9a..21dfae9d 100644
--- a/registry/handlers/api_test.go
+++ b/registry/handlers/api_test.go
@@ -340,7 +340,7 @@ func TestCatalogAPI(t *testing.T) {
 	defer resp.Body.Close()
 
 	checkResponse(t, "issuing catalog api check", resp, http.StatusBadRequest)
-	checkBodyHasErrorCodes(t, "invalid number of results requested", resp, v2.ErrorCodePaginationNumberInvalid)
+	checkBodyHasErrorCodes(t, "invalid number of results requested", resp, errcode.ErrorCodePaginationNumberInvalid)
 
 	// -----------------------------------
 	// Case No. 6: request n > maxentries but <= total catalog
@@ -361,7 +361,7 @@ func TestCatalogAPI(t *testing.T) {
 	defer resp.Body.Close()
 
 	checkResponse(t, "issuing catalog api check", resp, http.StatusBadRequest)
-	checkBodyHasErrorCodes(t, "invalid number of results requested", resp, v2.ErrorCodePaginationNumberInvalid)
+	checkBodyHasErrorCodes(t, "invalid number of results requested", resp, errcode.ErrorCodePaginationNumberInvalid)
 
 	// -----------------------------------
 	// Case No. 7: n = 0
@@ -410,7 +410,7 @@ func TestCatalogAPI(t *testing.T) {
 	defer resp.Body.Close()
 
 	checkResponse(t, "issuing catalog api check", resp, http.StatusBadRequest)
-	checkBodyHasErrorCodes(t, "invalid number of results requested", resp, v2.ErrorCodePaginationNumberInvalid)
+	checkBodyHasErrorCodes(t, "invalid number of results requested", resp, errcode.ErrorCodePaginationNumberInvalid)
 
 	// -----------------------------------
 	// Case No. 9: n = 5, max = 5, total catalog = 4
@@ -505,13 +505,13 @@ func TestTagsAPI(t *testing.T) {
 			name:               "negative n query parameter",
 			queryParams:        url.Values{"n": []string{"-1"}},
 			expectedStatusCode: http.StatusBadRequest,
-			expectedBodyErr:    &v2.ErrorCodePaginationNumberInvalid,
+			expectedBodyErr:    &errcode.ErrorCodePaginationNumberInvalid,
 		},
 		{
 			name:               "non integer n query parameter",
 			queryParams:        url.Values{"n": []string{"foo"}},
 			expectedStatusCode: http.StatusBadRequest,
-			expectedBodyErr:    &v2.ErrorCodePaginationNumberInvalid,
+			expectedBodyErr:    &errcode.ErrorCodePaginationNumberInvalid,
 		},
 		{
 			name:               "1st page",
@@ -901,7 +901,7 @@ func testBlobAPI(t *testing.T, env *testEnv, args blobArgs) *testEnv {
 	defer resp.Body.Close()
 
 	checkResponse(t, "bad layer push", resp, http.StatusBadRequest)
-	checkBodyHasErrorCodes(t, "bad layer push", resp, v2.ErrorCodeDigestInvalid)
+	checkBodyHasErrorCodes(t, "bad layer push", resp, errcode.ErrorCodeDigestInvalid)
 
 	// -----------------------------------------
 	// Do layer push with an empty body and correct digest
@@ -1343,7 +1343,7 @@ func TestManifestAPI_DeleteTag_Unknown(t *testing.T) {
 	defer resp.Body.Close()
 
 	checkResponse(t, msg, resp, http.StatusNotFound)
-	checkBodyHasErrorCodes(t, msg, resp, v2.ErrorCodeManifestUnknown)
+	checkBodyHasErrorCodes(t, msg, resp, errcode.ErrorCodeManifestUnknown)
 }
 
 func TestManifestAPI_DeleteTag_ReadOnly(t *testing.T) {
@@ -1443,7 +1443,7 @@ func TestGetManifestWithStorageError(t *testing.T) {
 	defer env1.Shutdown()
 
 	repo, _ := reference.WithName(repositoryWithManifestNotFound)
-	testManifestWithStorageError(t, env1, repo, http.StatusNotFound, v2.ErrorCodeManifestUnknown)
+	testManifestWithStorageError(t, env1, repo, http.StatusNotFound, errcode.ErrorCodeManifestUnknown)
 
 	repo, _ = reference.WithName(repositoryWithGenericStorageError)
 	testManifestWithStorageError(t, env1, repo, http.StatusInternalServerError, errcode.ErrorCodeUnknown)
@@ -1529,7 +1529,7 @@ func testManifestAPISchema2(t *testing.T, env *testEnv, imageName reference.Name
 	defer resp.Body.Close()
 
 	checkResponse(t, "getting non-existent manifest", resp, http.StatusNotFound)
-	checkBodyHasErrorCodes(t, "getting non-existent manifest", resp, v2.ErrorCodeManifestUnknown)
+	checkBodyHasErrorCodes(t, "getting non-existent manifest", resp, errcode.ErrorCodeManifestUnknown)
 
 	tagsURL, err := env.builder.BuildTagsURL(imageName)
 	if err != nil {
@@ -1544,7 +1544,7 @@ func testManifestAPISchema2(t *testing.T, env *testEnv, imageName reference.Name
 
 	// Check that we get an unknown repository error when asking for tags
 	checkResponse(t, "getting unknown manifest tags", resp, http.StatusNotFound)
-	checkBodyHasErrorCodes(t, "getting unknown manifest tags", resp, v2.ErrorCodeNameUnknown)
+	checkBodyHasErrorCodes(t, "getting unknown manifest tags", resp, errcode.ErrorCodeNameUnknown)
 
 	// --------------------------------
 	// Attempt to push manifest with missing config and missing layers
@@ -1575,10 +1575,10 @@ func testManifestAPISchema2(t *testing.T, env *testEnv, imageName reference.Name
 	resp = putManifest(t, "putting missing config manifest", manifestURL, schema2.MediaTypeManifest, manifest)
 	defer resp.Body.Close()
 	checkResponse(t, "putting missing config manifest", resp, http.StatusBadRequest)
-	_, p, counts := checkBodyHasErrorCodes(t, "putting missing config manifest", resp, v2.ErrorCodeManifestBlobUnknown)
+	_, p, counts := checkBodyHasErrorCodes(t, "putting missing config manifest", resp, errcode.ErrorCodeManifestBlobUnknown)
 
 	expectedCounts := map[errcode.ErrorCode]int{
-		v2.ErrorCodeManifestBlobUnknown: 3,
+		errcode.ErrorCodeManifestBlobUnknown: 3,
 	}
 
 	if !reflect.DeepEqual(counts, expectedCounts) {
@@ -1617,10 +1617,10 @@ func testManifestAPISchema2(t *testing.T, env *testEnv, imageName reference.Name
 	resp = putManifest(t, "putting missing layer manifest", manifestURL, schema2.MediaTypeManifest, manifest)
 	defer resp.Body.Close()
 	checkResponse(t, "putting missing layer manifest", resp, http.StatusBadRequest)
-	_, p, counts = checkBodyHasErrorCodes(t, "getting unknown manifest tags", resp, v2.ErrorCodeManifestBlobUnknown)
+	_, p, counts = checkBodyHasErrorCodes(t, "getting unknown manifest tags", resp, errcode.ErrorCodeManifestBlobUnknown)
 
 	expectedCounts = map[errcode.ErrorCode]int{
-		v2.ErrorCodeManifestBlobUnknown: 2,
+		errcode.ErrorCodeManifestBlobUnknown: 2,
 	}
 
 	if !reflect.DeepEqual(counts, expectedCounts) {
@@ -1841,10 +1841,10 @@ func testManifestAPIManifestList(t *testing.T, env *testEnv, args manifestArgs)
 	resp := putManifest(t, "putting missing manifest manifestlist", manifestURL, manifestlist.MediaTypeManifestList, manifestList)
 	defer resp.Body.Close()
 	checkResponse(t, "putting missing manifest manifestlist", resp, http.StatusBadRequest)
-	_, p, counts := checkBodyHasErrorCodes(t, "putting missing manifest manifestlist", resp, v2.ErrorCodeManifestBlobUnknown)
+	_, p, counts := checkBodyHasErrorCodes(t, "putting missing manifest manifestlist", resp, errcode.ErrorCodeManifestBlobUnknown)
 
 	expectedCounts := map[errcode.ErrorCode]int{
-		v2.ErrorCodeManifestBlobUnknown: 1,
+		errcode.ErrorCodeManifestBlobUnknown: 1,
 	}
 
 	if !reflect.DeepEqual(counts, expectedCounts) {
diff --git a/registry/proxy/proxytagservice_test.go b/registry/proxy/proxytagservice_test.go
index e31a44eb..61e15852 100644
--- a/registry/proxy/proxytagservice_test.go
+++ b/registry/proxy/proxytagservice_test.go
@@ -49,7 +49,7 @@ func (m *mockTagStore) All(ctx context.Context) ([]string, error) {
 	m.Lock()
 	defer m.Unlock()
 
-	tags := make([]string, 0, len(m.mapping))
+	var tags []string
 	for tag := range m.mapping {
 		tags = append(tags, tag)
 	}
diff --git a/registry/storage/driver/s3-aws/s3_test.go b/registry/storage/driver/s3-aws/s3_test.go
index 4987c52d..9f39975b 100644
--- a/registry/storage/driver/s3-aws/s3_test.go
+++ b/registry/storage/driver/s3-aws/s3_test.go
@@ -500,7 +500,7 @@ func TestWalk(t *testing.T) {
 	}
 
 	// create file structure matching fileset above
-	created := make([]string, 0, len(fileset))
+	var created []string
 	for _, p := range fileset {
 		err := drvr.PutContent(context.Background(), p, []byte("content "+p))
 		if err != nil {
diff --git a/testutil/manifests.go b/testutil/manifests.go
index 96af5703..9501aace 100644
--- a/testutil/manifests.go
+++ b/testutil/manifests.go
@@ -14,7 +14,7 @@ import (
 func MakeManifestList(blobstatter distribution.BlobStatter, manifestDigests []digest.Digest) (*manifestlist.DeserializedManifestList, error) {
 	ctx := context.Background()
 
-	manifestDescriptors := make([]manifestlist.ManifestDescriptor, 0, len(manifestDigests))
+	var manifestDescriptors []manifestlist.ManifestDescriptor
 	for _, manifestDigest := range manifestDigests {
 		descriptor, err := blobstatter.Stat(ctx, manifestDigest)
 		if err != nil {