Repository: theupdateframework/go-tuf
Pull request #602 (2024-02-05 19:53:46)

Refactor errors to use pointer receivers
This PR changes all errors to use pointer receivers, as is common Go idiom.

This doesn't change any behavior. It started as my attempt to fix something I thought was a bug, but I think I misunderstood. I won't feel bad if you decide to close/reject as this doesn't change any behavior and introduces a lot of LoC changes.

Pointer receivers have some benefits for use in error handling -- notably you can compare errors to nil (`if err == nil` vs `if err == MyError{}`). The choice is somewhat arbitrary, but using pointers is far more conventional.

rdimitrov: @codysoyland - That's nice! 💯 Thank you for addressing this! 👍 

Patch:
diff --git a/metadata/errors.go b/metadata/errors.go
index 38fcc19..3bd8e5e 100644
--- a/metadata/errors.go
+++ b/metadata/errors.go
@@ -34,22 +34,33 @@ type ErrRepository struct {
 	Msg string
 }
 
-func (e ErrRepository) Error() string {
+func (e *ErrRepository) Error() string {
 	return fmt.Sprintf("repository error: %s", e.Msg)
 }
 
+func (e *ErrRepository) Is(target error) bool {
+	_, ok := target.(*ErrRepository)
+	return ok
+}
+
 // ErrUnsignedMetadata - An error about metadata object with insufficient threshold of signatures
 type ErrUnsignedMetadata struct {
 	Msg string
 }
 
-func (e ErrUnsignedMetadata) Error() string {
+func (e *ErrUnsignedMetadata) Error() string {
 	return fmt.Sprintf("unsigned metadata error: %s", e.Msg)
 }
 
 // ErrUnsignedMetadata is a subset of ErrRepository
-func (e ErrUnsignedMetadata) Is(target error) bool {
-	return target == ErrRepository{} || target == ErrUnsignedMetadata{}
+func (e *ErrUnsignedMetadata) Is(target error) bool {
+	if _, ok := target.(*ErrUnsignedMetadata); ok {
+		return true
+	}
+	if _, ok := target.(*ErrRepository); ok {
+		return true
+	}
+	return false
 }
 
 // ErrBadVersionNumber - An error for metadata that contains an invalid version number
@@ -57,13 +68,19 @@ type ErrBadVersionNumber struct {
 	Msg string
 }
 
-func (e ErrBadVersionNumber) Error() string {
+func (e *ErrBadVersionNumber) Error() string {
 	return fmt.Sprintf("bad version number error: %s", e.Msg)
 }
 
 // ErrBadVersionNumber is a subset of ErrRepository
-func (e ErrBadVersionNumber) Is(target error) bool {
-	return target == ErrRepository{} || target == ErrBadVersionNumber{}
+func (e *ErrBadVersionNumber) Is(target error) bool {
+	if _, ok := target.(*ErrBadVersionNumber); ok {
+		return true
+	}
+	if _, ok := target.(*ErrRepository); ok {
+		return true
+	}
+	return false
 }
 
 // ErrEqualVersionNumber - An error for metadata containing a previously verified version number
@@ -71,13 +88,22 @@ type ErrEqualVersionNumber struct {
 	Msg string
 }
 
-func (e ErrEqualVersionNumber) Error() string {
+func (e *ErrEqualVersionNumber) Error() string {
 	return fmt.Sprintf("equal version number error: %s", e.Msg)
 }
 
 // ErrEqualVersionNumber is a subset of both ErrRepository and ErrBadVersionNumber
-func (e ErrEqualVersionNumber) Is(target error) bool {
-	return target == ErrRepository{} || target == ErrBadVersionNumber{} || target == ErrEqualVersionNumber{}
+func (e *ErrEqualVersionNumber) Is(target error) bool {
+	if _, ok := target.(*ErrEqualVersionNumber); ok {
+		return true
+	}
+	if _, ok := target.(*ErrBadVersionNumber); ok {
+		return true
+	}
+	if _, ok := target.(*ErrRepository); ok {
+		return true
+	}
+	return false
 }
 
 // ErrExpiredMetadata - Indicate that a TUF Metadata file has expired
@@ -85,13 +111,19 @@ type ErrExpiredMetadata struct {
 	Msg string
 }
 
-func (e ErrExpiredMetadata) Error() string {
+func (e *ErrExpiredMetadata) Error() string {
 	return fmt.Sprintf("expired metadata error: %s", e.Msg)
 }
 
 // ErrExpiredMetadata is a subset of ErrRepository
-func (e ErrExpiredMetadata) Is(target error) bool {
-	return target == ErrRepository{} || target == ErrExpiredMetadata{}
+func (e *ErrExpiredMetadata) Is(target error) bool {
+	if _, ok := target.(*ErrExpiredMetadata); ok {
+		return true
+	}
+	if _, ok := target.(*ErrRepository); ok {
+		return true
+	}
+	return false
 }
 
 // ErrLengthOrHashMismatch - An error while checking the length and hash values of an object
@@ -99,13 +131,19 @@ type ErrLengthOrHashMismatch struct {
 	Msg string
 }
 
-func (e ErrLengthOrHashMismatch) Error() string {
+func (e *ErrLengthOrHashMismatch) Error() string {
 	return fmt.Sprintf("length/hash verification error: %s", e.Msg)
 }
 
 // ErrLengthOrHashMismatch is a subset of ErrRepository
-func (e ErrLengthOrHashMismatch) Is(target error) bool {
-	return target == ErrRepository{} || target == ErrLengthOrHashMismatch{}
+func (e *ErrLengthOrHashMismatch) Is(target error) bool {
+	if _, ok := target.(*ErrLengthOrHashMismatch); ok {
+		return true
+	}
+	if _, ok := target.(*ErrRepository); ok {
+		return true
+	}
+	return false
 }
 
 // Download errors
@@ -115,22 +153,33 @@ type ErrDownload struct {
 	Msg string
 }
 
-func (e ErrDownload) Error() string {
+func (e *ErrDownload) Error() string {
 	return fmt.Sprintf("download error: %s", e.Msg)
 }
 
+func (e *ErrDownload) Is(target error) bool {
+	_, ok := target.(*ErrDownload)
+	return ok
+}
+
 // ErrDownloadLengthMismatch - Indicate that a mismatch of lengths was seen while downloading a file
 type ErrDownloadLengthMismatch struct {
 	Msg string
 }
 
-func (e ErrDownloadLengthMismatch) Error() string {
+func (e *ErrDownloadLengthMismatch) Error() string {
 	return fmt.Sprintf("download length mismatch error: %s", e.Msg)
 }
 
 // ErrDownloadLengthMismatch is a subset of ErrDownload
-func (e ErrDownloadLengthMismatch) Is(target error) bool {
-	return target == ErrDownload{} || target == ErrDownloadLengthMismatch{}
+func (e *ErrDownloadLengthMismatch) Is(target error) bool {
+	if _, ok := target.(*ErrDownloadLengthMismatch); ok {
+		return true
+	}
+	if _, ok := target.(*ErrDownload); ok {
+		return true
+	}
+	return false
 }
 
 // ErrDownloadHTTP - Returned by Fetcher interface implementations for HTTP errors
@@ -139,13 +188,19 @@ type ErrDownloadHTTP struct {
 	URL        string
 }
 
-func (e ErrDownloadHTTP) Error() string {
+func (e *ErrDownloadHTTP) Error() string {
 	return fmt.Sprintf("failed to download %s, http status code: %d", e.URL, e.StatusCode)
 }
 
 // ErrDownloadHTTP is a subset of ErrDownload
-func (e ErrDownloadHTTP) Is(target error) bool {
-	return target == ErrDownload{} || target == ErrDownloadHTTP{}
+func (e *ErrDownloadHTTP) Is(target error) bool {
+	if _, ok := target.(*ErrDownloadHTTP); ok {
+		return true
+	}
+	if _, ok := target.(*ErrDownload); ok {
+		return true
+	}
+	return false
 }
 
 // ValueError
@@ -153,24 +208,39 @@ type ErrValue struct {
 	Msg string
 }
 
-func (e ErrValue) Error() string {
+func (e *ErrValue) Error() string {
 	return fmt.Sprintf("value error: %s", e.Msg)
 }
 
+func (e *ErrValue) Is(err error) bool {
+	_, ok := err.(*ErrValue)
+	return ok
+}
+
 // TypeError
 type ErrType struct {
 	Msg string
 }
 
-func (e ErrType) Error() string {
+func (e *ErrType) Error() string {
 	return fmt.Sprintf("type error: %s", e.Msg)
 }
 
+func (e *ErrType) Is(err error) bool {
+	_, ok := err.(*ErrType)
+	return ok
+}
+
 // RuntimeError
 type ErrRuntime struct {
 	Msg string
 }
 
-func (e ErrRuntime) Error() string {
+func (e *ErrRuntime) Error() string {
 	return fmt.Sprintf("runtime error: %s", e.Msg)
 }
+
+func (e *ErrRuntime) Is(err error) bool {
+	_, ok := err.(*ErrRuntime)
+	return ok
+}
diff --git a/metadata/fetcher/fetcher.go b/metadata/fetcher/fetcher.go
index c3e812b..4923472 100644
--- a/metadata/fetcher/fetcher.go
+++ b/metadata/fetcher/fetcher.go
@@ -57,7 +57,7 @@ func (d *DefaultFetcher) DownloadFile(urlPath string, maxLength int64, timeout t
 	defer res.Body.Close()
 	// Handle HTTP status codes.
 	if res.StatusCode == http.StatusNotFound || res.StatusCode == http.StatusForbidden || res.StatusCode != http.StatusOK {
-		return nil, metadata.ErrDownloadHTTP{StatusCode: res.StatusCode, URL: urlPath}
+		return nil, &metadata.ErrDownloadHTTP{StatusCode: res.StatusCode, URL: urlPath}
 	}
 	var length int64
 	// Get content length from header (might not be accurate, -1 or not set).
@@ -68,7 +68,7 @@ func (d *DefaultFetcher) DownloadFile(urlPath string, maxLength int64, timeout t
 		}
 		// Error if the reported size is greater than what is expected.
 		if length > maxLength {
-			return nil, metadata.ErrDownloadLengthMismatch{Msg: fmt.Sprintf("download failed for %s, length %d is larger than expected %d", urlPath, length, maxLength)}
+			return nil, &metadata.ErrDownloadLengthMismatch{Msg: fmt.Sprintf("download failed for %s, length %d is larger than expected %d", urlPath, length, maxLength)}
 		}
 	}
 	// Although the size has been checked above, use a LimitReader in case
@@ -82,7 +82,7 @@ func (d *DefaultFetcher) DownloadFile(urlPath string, maxLength int64, timeout t
 	// Error if the reported size is greater than what is expected.
 	length = int64(len(data))
 	if length > maxLength {
-		return nil, metadata.ErrDownloadLengthMismatch{Msg: fmt.Sprintf("download failed for %s, length %d is larger than expected %d", urlPath, length, maxLength)}
+		return nil, &metadata.ErrDownloadLengthMismatch{Msg: fmt.Sprintf("download failed for %s, length %d is larger than expected %d", urlPath, length, maxLength)}
 	}
 
 	return data, nil
diff --git a/metadata/marshal.go b/metadata/marshal.go
index 97cf351..bd3f1e4 100644
--- a/metadata/marshal.go
+++ b/metadata/marshal.go
@@ -335,7 +335,7 @@ func (meta *Metadata[T]) UnmarshalJSON(data []byte) error {
 		meta.Signed = i.(T)
 		meta.Signatures = dict.Signatures
 	default:
-		return ErrValue{Msg: "unrecognized metadata type"}
+		return &ErrValue{Msg: "unrecognized metadata type"}
 	}
 	delete(m, "signed")
 	delete(m, "signatures")
@@ -470,7 +470,7 @@ func (role DelegatedRole) MarshalJSON() ([]byte, error) {
 	dict["terminating"] = role.Terminating
 	// make sure we have only one of the two (per spec)
 	if role.Paths != nil && role.PathHashPrefixes != nil {
-		return nil, ErrValue{Msg: "failed to marshal: not allowed to have both \"paths\" and \"path_hash_prefixes\" present"}
+		return nil, &ErrValue{Msg: "failed to marshal: not allowed to have both \"paths\" and \"path_hash_prefixes\" present"}
 	}
 	if role.Paths != nil {
 		dict["paths"] = role.Paths
diff --git a/metadata/metadata.go b/metadata/metadata.go
index e7b8ce3..8bfecbb 100644
--- a/metadata/metadata.go
+++ b/metadata/metadata.go
@@ -218,7 +218,7 @@ func (meta *Metadata[T]) Sign(signer signature.Signer) (*Signature, error) {
 	// sign the Signed part
 	sb, err := signer.SignMessage(bytes.NewReader(payload))
 	if err != nil {
-		return nil, ErrUnsignedMetadata{Msg: "problem signing metadata"}
+		return nil, &ErrUnsignedMetadata{Msg: "problem signing metadata"}
 	}
 	// get the signer's PublicKey
 	publ, err := signer.PublicKey()
@@ -263,12 +263,12 @@ func (meta *Metadata[T]) VerifyDelegate(delegatedRole string, delegatedMetadata
 			roleThreshold = role.Threshold
 		} else {
 			// the delegated role was not found, no need to proceed
-			return ErrValue{Msg: fmt.Sprintf("no delegation found for %s", delegatedRole)}
+			return &ErrValue{Msg: fmt.Sprintf("no delegation found for %s", delegatedRole)}
 		}
 	// Targets delegator
 	case *Metadata[TargetsType]:
 		if i.Signed.Delegations == nil {
-			return ErrValue{Msg: "no delegations found"}
+			return &ErrValue{Msg: "no delegations found"}
 		}
 		keys = i.Signed.Delegations.Keys
 		if i.Signed.Delegations.Roles != nil {
@@ -283,24 +283,24 @@ func (meta *Metadata[T]) VerifyDelegate(delegatedRole string, delegatedMetadata
 			}
 			// the delegated role was not found, no need to proceed
 			if !found {
-				return ErrValue{Msg: fmt.Sprintf("no delegation found for %s", delegatedRole)}
+				return &ErrValue{Msg: fmt.Sprintf("no delegation found for %s", delegatedRole)}
 			}
 		} else if i.Signed.Delegations.SuccinctRoles != nil {
 			roleKeyIDs = i.Signed.Delegations.SuccinctRoles.KeyIDs
 			roleThreshold = i.Signed.Delegations.SuccinctRoles.Threshold
 		}
 	default:
-		return ErrType{Msg: "call is valid only on delegator metadata (should be either root or targets)"}
+		return &ErrType{Msg: "call is valid only on delegator metadata (should be either root or targets)"}
 	}
 	// if there are no keyIDs for that role it means there's no delegation found
 	if len(roleKeyIDs) == 0 {
-		return ErrValue{Msg: fmt.Sprintf("no delegation found for %s", delegatedRole)}
+		return &ErrValue{Msg: fmt.Sprintf("no delegation found for %s", delegatedRole)}
 	}
 	// loop through each role keyID
 	for _, keyID := range roleKeyIDs {
 		key, ok := keys[keyID]
 		if !ok {
-			return ErrValue{Msg: fmt.Sprintf("key with ID %s not found in %s keyids", keyID, delegatedRole)}
+			return &ErrValue{Msg: fmt.Sprintf("key with ID %s not found in %s keyids", keyID, delegatedRole)}
 		}
 		sign := Signature{}
 		var payload []byte
@@ -363,7 +363,7 @@ func (meta *Metadata[T]) VerifyDelegate(delegatedRole string, delegatedMetadata
 				return err
 			}
 		default:
-			return ErrType{Msg: "unknown delegated metadata type"}
+			return &ErrType{Msg: "unknown delegated metadata type"}
 		}
 		// verify if the signature for that payload corresponds to the given key
 		if err := verifier.VerifySignature(bytes.NewReader(sign.Signature), bytes.NewReader(payload)); err != nil {
@@ -378,7 +378,7 @@ func (meta *Metadata[T]) VerifyDelegate(delegatedRole string, delegatedMetadata
 	// check if the amount of valid signatures is enough
 	if len(signingKeys) < roleThreshold {
 		log.Info("Verifying failed, not enough signatures", "role", delegatedRole, "got", len(signingKeys), "want", roleThreshold)
-		return ErrUnsignedMetadata{Msg: fmt.Sprintf("Verifying %s failed, not enough signatures, got %d, want %d", delegatedRole, len(signingKeys), roleThreshold)}
+		return &ErrUnsignedMetadata{Msg: fmt.Sprintf("Verifying %s failed, not enough signatures, got %d, want %d", delegatedRole, len(signingKeys), roleThreshold)}
 	}
 	log.Info("Verified successfully", "role", delegatedRole)
 	return nil
@@ -490,7 +490,7 @@ func (t *TargetFiles) FromBytes(localPath string, data []byte, hashes ...string)
 		case "sha512":
 			hasher = sha512.New()
 		default:
-			return nil, ErrValue{Msg: fmt.Sprintf("failed generating TargetFile - unsupported hashing algorithm - %s", v)}
+			return nil, &ErrValue{Msg: fmt.Sprintf("failed generating TargetFile - unsupported hashing algorithm - %s", v)}
 		}
 		_, err := hasher.Write(data)
 		if err != nil {
@@ -653,7 +653,7 @@ func (role *SuccinctRoles) IsDelegatedRole(roleName string) bool {
 func (signed *RootType) AddKey(key *Key, role string) error {
 	// verify role is present
 	if _, ok := signed.Roles[role]; !ok {
-		return ErrValue{Msg: fmt.Sprintf("role %s doesn't exist", role)}
+		return &ErrValue{Msg: fmt.Sprintf("role %s doesn't exist", role)}
 	}
 	// add keyID to role
 	if !slices.Contains(signed.Roles[role].KeyIDs, key.ID()) {
@@ -670,11 +670,11 @@ func (signed *RootType) AddKey(key *Key, role string) error {
 func (signed *RootType) RevokeKey(keyID, role string) error {
 	// verify role is present
 	if _, ok := signed.Roles[role]; !ok {
-		return ErrValue{Msg: fmt.Sprintf("role %s doesn't exist", role)}
+		return &ErrValue{Msg: fmt.Sprintf("role %s doesn't exist", role)}
 	}
 	// verify keyID is present for given role
 	if !slices.Contains(signed.Roles[role].KeyIDs, keyID) {
-		return ErrValue{Msg: fmt.Sprintf("key with id %s is not used by %s", keyID, role)}
+		return &ErrValue{Msg: fmt.Sprintf("key with id %s is not used by %s", keyID, role)}
 	}
 	// remove keyID from role
 	filteredKeyIDs := []string{}
@@ -703,7 +703,7 @@ func (signed *RootType) RevokeKey(keyID, role string) error {
 func (signed *TargetsType) AddKey(key *Key, role string) error {
 	// check if Delegations are even present
 	if signed.Delegations == nil {
-		return ErrValue{Msg: fmt.Sprintf("delegated role %s doesn't exist", role)}
+		return &ErrValue{Msg: fmt.Sprintf("delegated role %s doesn't exist", role)}
 	}
 	// standard delegated roles
 	if signed.Delegations.Roles != nil {
@@ -723,7 +723,7 @@ func (signed *TargetsType) AddKey(key *Key, role string) error {
 			}
 		}
 		if !isDelegatedRole {
-			return ErrValue{Msg: fmt.Sprintf("delegated role %s doesn't exist", role)}
+			return &ErrValue{Msg: fmt.Sprintf("delegated role %s doesn't exist", role)}
 		}
 	} else if signed.Delegations.SuccinctRoles != nil {
 		// add key if keyID is not already part of keyIDs for the SuccinctRoles role
@@ -745,7 +745,7 @@ func (signed *TargetsType) AddKey(key *Key, role string) error {
 func (signed *TargetsType) RevokeKey(keyID string, role string) error {
 	// check if Delegations are even present
 	if signed.Delegations == nil {
-		return ErrValue{Msg: fmt.Sprintf("delegated role %s doesn't exist", role)}
+		return &ErrValue{Msg: fmt.Sprintf("delegated role %s doesn't exist", role)}
 	}
 	// standard delegated roles
 	if signed.Delegations.Roles != nil {
@@ -755,7 +755,7 @@ func (signed *TargetsType) RevokeKey(keyID string, role string) error {
 			if d.Name == role {
 				// check if keyID is present in keyIDs for that role
 				if !slices.Contains(d.KeyIDs, keyID) {
-					return ErrValue{Msg: fmt.Sprintf("key with id %s is not used by %s", keyID, role)}
+					return &ErrValue{Msg: fmt.Sprintf("key with id %s is not used by %s", keyID, role)}
 				}
 				// remove keyID from role
 				filteredKeyIDs := []string{}
@@ -778,11 +778,11 @@ func (signed *TargetsType) RevokeKey(keyID string, role string) error {
 			}
 		}
 		// we haven't found the delegated role
-		return ErrValue{Msg: fmt.Sprintf("delegated role %s doesn't exist", role)}
+		return &ErrValue{Msg: fmt.Sprintf("delegated role %s doesn't exist", role)}
 	} else if signed.Delegations.SuccinctRoles != nil {
 		// check if keyID is used by SuccinctRoles role
 		if !slices.Contains(signed.Delegations.SuccinctRoles.KeyIDs, keyID) {
-			return ErrValue{Msg: fmt.Sprintf("key with id %s is not used by SuccinctRoles", keyID)}
+			return &ErrValue{Msg: fmt.Sprintf("key with id %s is not used by SuccinctRoles", keyID)}
 		}
 		// remove keyID from the SuccinctRoles role
 		filteredKeyIDs := []string{}
@@ -798,7 +798,7 @@ func (signed *TargetsType) RevokeKey(keyID string, role string) error {
 		delete(signed.Delegations.Keys, keyID)
 		return nil
 	}
-	return ErrValue{Msg: fmt.Sprintf("delegated role %s doesn't exist", role)}
+	return &ErrValue{Msg: fmt.Sprintf("delegated role %s doesn't exist", role)}
 }
 
 // Equal checks whether one hash set equals another
@@ -824,7 +824,7 @@ func verifyLength(data []byte, length int64) error {
 		return err
 	}
 	if length != len {
-		return ErrLengthOrHashMismatch{Msg: fmt.Sprintf("length verification failed - expected %d, got %d", length, len)}
+		return &ErrLengthOrHashMismatch{Msg: fmt.Sprintf("length verification failed - expected %d, got %d", length, len)}
 	}
 	return nil
 }
@@ -839,11 +839,11 @@ func verifyHashes(data []byte, hashes Hashes) error {
 		case "sha512":
 			hasher = sha512.New()
 		default:
-			return ErrLengthOrHashMismatch{Msg: fmt.Sprintf("hash verification failed - unknown hashing algorithm - %s", k)}
+			return &ErrLengthOrHashMismatch{Msg: fmt.Sprintf("hash verification failed - unknown hashing algorithm - %s", k)}
 		}
 		hasher.Write(data)
 		if hex.EncodeToString(v) != hex.EncodeToString(hasher.Sum(nil)) {
-			return ErrLengthOrHashMismatch{Msg: fmt.Sprintf("hash verification failed - mismatch for algorithm %s", k)}
+			return &ErrLengthOrHashMismatch{Msg: fmt.Sprintf("hash verification failed - mismatch for algorithm %s", k)}
 		}
 	}
 	return nil
@@ -873,7 +873,7 @@ func checkUniqueSignatures[T Roles](meta Metadata[T]) error {
 	signatures := []string{}
 	for _, sig := range meta.Signatures {
 		if slices.Contains(signatures, sig.KeyID) {
-			return ErrValue{Msg: fmt.Sprintf("multiple signatures found for key ID %s", sig.KeyID)}
+			return &ErrValue{Msg: fmt.Sprintf("multiple signatures found for key ID %s", sig.KeyID)}
 		}
 		signatures = append(signatures, sig.KeyID)
 	}
@@ -891,22 +891,22 @@ func checkType[T Roles](data []byte) error {
 	switch i.(type) {
 	case *RootType:
 		if ROOT != signedType {
-			return ErrValue{Msg: fmt.Sprintf("expected metadata type %s, got - %s", ROOT, signedType)}
+			return &ErrValue{Msg: fmt.Sprintf("expected metadata type %s, got - %s", ROOT, signedType)}
 		}
 	case *SnapshotType:
 		if SNAPSHOT != signedType {
-			return ErrValue{Msg: fmt.Sprintf("expected metadata type %s, got - %s", SNAPSHOT, signedType)}
+			return &ErrValue{Msg: fmt.Sprintf("expected metadata type %s, got - %s", SNAPSHOT, signedType)}
 		}
 	case *TimestampType:
 		if TIMESTAMP != signedType {
-			return ErrValue{Msg: fmt.Sprintf("expected metadata type %s, got - %s", TIMESTAMP, signedType)}
+			return &ErrValue{Msg: fmt.Sprintf("expected metadata type %s, got - %s", TIMESTAMP, signedType)}
 		}
 	case *TargetsType:
 		if TARGETS != signedType {
-			return ErrValue{Msg: fmt.Sprintf("expected metadata type %s, got - %s", TARGETS, signedType)}
+			return &ErrValue{Msg: fmt.Sprintf("expected metadata type %s, got - %s", TARGETS, signedType)}
 		}
 	default:
-		return ErrValue{Msg: fmt.Sprintf("unrecognized metadata type - %s", signedType)}
+		return &ErrValue{Msg: fmt.Sprintf("unrecognized metadata type - %s", signedType)}
 	}
 	// all okay
 	return nil
diff --git a/metadata/trustedmetadata/trustedmetadata.go b/metadata/trustedmetadata/trustedmetadata.go
index 7185fe8..0726f31 100644
--- a/metadata/trustedmetadata/trustedmetadata.go
+++ b/metadata/trustedmetadata/trustedmetadata.go
@@ -58,7 +58,7 @@ func (trusted *TrustedMetadata) UpdateRoot(rootData []byte) (*metadata.Metadata[
 	log := metadata.GetLogger()
 
 	if trusted.Timestamp != nil {
-		return nil, metadata.ErrRuntime{Msg: "cannot update root after timestamp"}
+		return nil, &metadata.ErrRuntime{Msg: "cannot update root after timestamp"}
 	}
 	log.Info("Updating root")
 	// generate root metadata
@@ -68,7 +68,7 @@ func (trusted *TrustedMetadata) UpdateRoot(rootData []byte) (*metadata.Metadata[
 	}
 	// check metadata type matches root
 	if newRoot.Signed.Type != metadata.ROOT {
-		return nil, metadata.ErrRepository{Msg: fmt.Sprintf("expected %s, got %s", metadata.ROOT, newRoot.Signed.Type)}
+		return nil, &metadata.ErrRepository{Msg: fmt.Sprintf("expected %s, got %s", metadata.ROOT, newRoot.Signed.Type)}
 	}
 	// verify that new root is signed by trusted root
 	err = trusted.Root.VerifyDelegate(metadata.ROOT, newRoot)
@@ -77,7 +77,7 @@ func (trusted *TrustedMetadata) UpdateRoot(rootData []byte) (*metadata.Metadata[
 	}
 	// verify version
 	if newRoot.Signed.Version != trusted.Root.Signed.Version+1 {
-		return nil, metadata.ErrBadVersionNumber{Msg: fmt.Sprintf("bad version number, expected %d, got %d", trusted.Root.Signed.Version+1, newRoot.Signed.Version)}
+		return nil, &metadata.ErrBadVersionNumber{Msg: fmt.Sprintf("bad version number, expected %d, got %d", trusted.Root.Signed.Version+1, newRoot.Signed.Version)}
 	}
 	// verify that new root is signed by itself
 	err = newRoot.VerifyDelegate(metadata.ROOT, newRoot)
@@ -100,13 +100,13 @@ func (trusted *TrustedMetadata) UpdateTimestamp(timestampData []byte) (*metadata
 	log := metadata.GetLogger()
 
 	if trusted.Snapshot != nil {
-		return nil, metadata.ErrRuntime{Msg: "cannot update timestamp after snapshot"}
+		return nil, &metadata.ErrRuntime{Msg: "cannot update timestamp after snapshot"}
 	}
 	// client workflow 5.3.10: Make sure final root is not expired.
 	if trusted.Root.Signed.IsExpired(trusted.RefTime) {
 		// no need to check for 5.3.11 (fast forward attack recovery):
 		// timestamp/snapshot can not yet be loaded at this point
-		return nil, metadata.ErrExpiredMetadata{Msg: "final root.json is expired"}
+		return nil, &metadata.ErrExpiredMetadata{Msg: "final root.json is expired"}
 	}
 	log.Info("Updating timestamp")
 	newTimestamp, err := metadata.Timestamp().FromBytes(timestampData)
@@ -115,7 +115,7 @@ func (trusted *TrustedMetadata) UpdateTimestamp(timestampData []byte) (*metadata
 	}
 	// check metadata type matches timestamp
 	if newTimestamp.Signed.Type != metadata.TIMESTAMP {
-		return nil, metadata.ErrRepository{Msg: fmt.Sprintf("expected %s, got %s", metadata.TIMESTAMP, newTimestamp.Signed.Type)}
+		return nil, &metadata.ErrRepository{Msg: fmt.Sprintf("expected %s, got %s", metadata.TIMESTAMP, newTimestamp.Signed.Type)}
 	}
 	// verify that new timestamp is signed by trusted root
 	err = trusted.Root.VerifyDelegate(metadata.TIMESTAMP, newTimestamp)
@@ -127,18 +127,18 @@ func (trusted *TrustedMetadata) UpdateTimestamp(timestampData []byte) (*metadata
 	if trusted.Timestamp != nil {
 		// prevent rolling back timestamp version
 		if newTimestamp.Signed.Version < trusted.Timestamp.Signed.Version {
-			return nil, metadata.ErrBadVersionNumber{Msg: fmt.Sprintf("new timestamp version %d must be >= %d", newTimestamp.Signed.Version, trusted.Timestamp.Signed.Version)}
+			return nil, &metadata.ErrBadVersionNumber{Msg: fmt.Sprintf("new timestamp version %d must be >= %d", newTimestamp.Signed.Version, trusted.Timestamp.Signed.Version)}
 		}
 		// keep using old timestamp if versions are equal
 		if newTimestamp.Signed.Version == trusted.Timestamp.Signed.Version {
 			log.Info("New timestamp version equals the old one", "new", newTimestamp.Signed.Version, "old", trusted.Timestamp.Signed.Version)
-			return nil, metadata.ErrEqualVersionNumber{Msg: fmt.Sprintf("new timestamp version %d equals the old one %d", newTimestamp.Signed.Version, trusted.Timestamp.Signed.Version)}
+			return nil, &metadata.ErrEqualVersionNumber{Msg: fmt.Sprintf("new timestamp version %d equals the old one %d", newTimestamp.Signed.Version, trusted.Timestamp.Signed.Version)}
 		}
 		// prevent rolling back snapshot version
 		snapshotMeta := trusted.Timestamp.Signed.Meta[fmt.Sprintf("%s.json", metadata.SNAPSHOT)]
 		newSnapshotMeta := newTimestamp.Signed.Meta[fmt.Sprintf("%s.json", metadata.SNAPSHOT)]
 		if newSnapshotMeta.Version < snapshotMeta.Version {
-			return nil, metadata.ErrBadVersionNumber{Msg: fmt.Sprintf("new snapshot version %d must be >= %d", newSnapshotMeta.Version, snapshotMeta.Version)}
+			return nil, &metadata.ErrBadVersionNumber{Msg: fmt.Sprintf("new snapshot version %d must be >= %d", newSnapshotMeta.Version, snapshotMeta.Version)}
 		}
 	}
 	// expiry not checked to allow old timestamp to be used for rollback
@@ -159,7 +159,7 @@ func (trusted *TrustedMetadata) UpdateTimestamp(timestampData []byte) (*metadata
 // checkFinalTimestamp verifies if trusted timestamp is not expired
 func (trusted *TrustedMetadata) checkFinalTimestamp() error {
 	if trusted.Timestamp.Signed.IsExpired(trusted.RefTime) {
-		return metadata.ErrExpiredMetadata{Msg: "timestamp.json is expired"}
+		return &metadata.ErrExpiredMetadata{Msg: "timestamp.json is expired"}
 	}
 	return nil
 }
@@ -176,10 +176,10 @@ func (trusted *TrustedMetadata) UpdateSnapshot(snapshotData []byte, isTrusted bo
 	log := metadata.GetLogger()
 
 	if trusted.Timestamp == nil {
-		return nil, metadata.ErrRuntime{Msg: "cannot update snapshot before timestamp"}
+		return nil, &metadata.ErrRuntime{Msg: "cannot update snapshot before timestamp"}
 	}
 	if trusted.Targets[metadata.TARGETS] != nil {
-		return nil, metadata.ErrRuntime{Msg: "cannot update snapshot after targets"}
+		return nil, &metadata.ErrRuntime{Msg: "cannot update snapshot after targets"}
 	}
 	log.Info("Updating snapshot")
 
@@ -203,7 +203,7 @@ func (trusted *TrustedMetadata) UpdateSnapshot(snapshotData []byte, isTrusted bo
 	}
 	// check metadata type matches snapshot
 	if newSnapshot.Signed.Type != metadata.SNAPSHOT {
-		return nil, metadata.ErrRepository{Msg: fmt.Sprintf("expected %s, got %s", metadata.SNAPSHOT, newSnapshot.Signed.Type)}
+		return nil, &metadata.ErrRepository{Msg: fmt.Sprintf("expected %s, got %s", metadata.SNAPSHOT, newSnapshot.Signed.Type)}
 	}
 	// verify that new snapshot is signed by trusted root
 	err = trusted.Root.VerifyDelegate(metadata.SNAPSHOT, newSnapshot)
@@ -220,11 +220,11 @@ func (trusted *TrustedMetadata) UpdateSnapshot(snapshotData []byte, isTrusted bo
 			newFileInfo, ok := newSnapshot.Signed.Meta[name]
 			// prevent removal of any metadata in meta
 			if !ok {
-				return nil, metadata.ErrRepository{Msg: fmt.Sprintf("new snapshot is missing info for %s", name)}
+				return nil, &metadata.ErrRepository{Msg: fmt.Sprintf("new snapshot is missing info for %s", name)}
 			}
 			// prevent rollback of any metadata versions
 			if newFileInfo.Version < info.Version {
-				return nil, metadata.ErrBadVersionNumber{Msg: fmt.Sprintf("expected %s version %d, got %d", name, newFileInfo.Version, info.Version)}
+				return nil, &metadata.ErrBadVersionNumber{Msg: fmt.Sprintf("expected %s version %d, got %d", name, newFileInfo.Version, info.Version)}
 			}
 		}
 	}
@@ -246,11 +246,11 @@ func (trusted *TrustedMetadata) UpdateSnapshot(snapshotData []byte, isTrusted bo
 // checkFinalSnapshot verifies if it's not expired and snapshot version matches timestamp meta version
 func (trusted *TrustedMetadata) checkFinalSnapshot() error {
 	if trusted.Snapshot.Signed.IsExpired(trusted.RefTime) {
-		return metadata.ErrExpiredMetadata{Msg: "snapshot.json is expired"}
+		return &metadata.ErrExpiredMetadata{Msg: "snapshot.json is expired"}
 	}
 	snapshotMeta := trusted.Timestamp.Signed.Meta[fmt.Sprintf("%s.json", metadata.SNAPSHOT)]
 	if trusted.Snapshot.Signed.Version != snapshotMeta.Version {
-		return metadata.ErrBadVersionNumber{Msg: fmt.Sprintf("expected %d, got %d", snapshotMeta.Version, trusted.Snapshot.Signed.Version)}
+		return &metadata.ErrBadVersionNumber{Msg: fmt.Sprintf("expected %d, got %d", snapshotMeta.Version, trusted.Snapshot.Signed.Version)}
 	}
 	return nil
 }
@@ -266,7 +266,7 @@ func (trusted *TrustedMetadata) UpdateDelegatedTargets(targetsData []byte, roleN
 
 	var ok bool
 	if trusted.Snapshot == nil {
-		return nil, metadata.ErrRuntime{Msg: "cannot load targets before snapshot"}
+		return nil, &metadata.ErrRuntime{Msg: "cannot load targets before snapshot"}
 	}
 	// targets cannot be loaded if final snapshot is expired or its version
 	// does not match meta version in timestamp
@@ -285,13 +285,13 @@ func (trusted *TrustedMetadata) UpdateDelegatedTargets(targetsData []byte, roleN
 		_, ok = trusted.Targets[delegatorName]
 	}
 	if !ok {
-		return nil, metadata.ErrRuntime{Msg: "cannot load targets before delegator"}
+		return nil, &metadata.ErrRuntime{Msg: "cannot load targets before delegator"}
 	}
 	log.Info("Updating delegated role", "role", roleName, "delegator", delegatorName)
 	// Verify against the hashes in snapshot, if any
 	meta, ok := trusted.Snapshot.Signed.Meta[fmt.Sprintf("%s.json", roleName)]
 	if !ok {
-		return nil, metadata.ErrRepository{Msg: fmt.Sprintf("snapshot does not contain information for %s", roleName)}
+		return nil, &metadata.ErrRepository{Msg: fmt.Sprintf("snapshot does not contain information for %s", roleName)}
 	}
 	err = meta.VerifyLengthHashes(targetsData)
 	if err != nil {
@@ -303,7 +303,7 @@ func (trusted *TrustedMetadata) UpdateDelegatedTargets(targetsData []byte, roleN
 	}
 	// check metadata type matches targets
 	if newDelegate.Signed.Type != metadata.TARGETS {
-		return nil, metadata.ErrRepository{Msg: fmt.Sprintf("expected %s, got %s", metadata.TARGETS, newDelegate.Signed.Type)}
+		return nil, &metadata.ErrRepository{Msg: fmt.Sprintf("expected %s, got %s", metadata.TARGETS, newDelegate.Signed.Type)}
 	}
 	// get delegator metadata and verify the new delegatee
 	if delegatorName == metadata.ROOT {
@@ -319,11 +319,11 @@ func (trusted *TrustedMetadata) UpdateDelegatedTargets(targetsData []byte, roleN
 	}
 	// check versions
 	if newDelegate.Signed.Version != meta.Version {
-		return nil, metadata.ErrBadVersionNumber{Msg: fmt.Sprintf("expected %s version %d, got %d", roleName, meta.Version, newDelegate.Signed.Version)}
+		return nil, &metadata.ErrBadVersionNumber{Msg: fmt.Sprintf("expected %s version %d, got %d", roleName, meta.Version, newDelegate.Signed.Version)}
 	}
 	// check expiration
 	if newDelegate.Signed.IsExpired(trusted.RefTime) {
-		return nil, metadata.ErrExpiredMetadata{Msg: fmt.Sprintf("new %s is expired", roleName)}
+		return nil, &metadata.ErrExpiredMetadata{Msg: fmt.Sprintf("new %s is expired", roleName)}
 	}
 	trusted.Targets[roleName] = newDelegate
 	log.Info("Updated role", "role", roleName, "version", trusted.Targets[roleName].Signed.Version)
@@ -343,7 +343,7 @@ func (trusted *TrustedMetadata) loadTrustedRoot(rootData []byte) error {
 	}
 	// check metadata type matches root
 	if newRoot.Signed.Type != metadata.ROOT {
-		return metadata.ErrRepository{Msg: fmt.Sprintf("expected %s, got %s", metadata.ROOT, newRoot.Signed.Type)}
+		return &metadata.ErrRepository{Msg: fmt.Sprintf("expected %s, got %s", metadata.ROOT, newRoot.Signed.Type)}
 	}
 	// verify root by itself
 	err = newRoot.VerifyDelegate(metadata.ROOT, newRoot)
diff --git a/metadata/updater/updater.go b/metadata/updater/updater.go
index 63169af..2ce4316 100644
--- a/metadata/updater/updater.go
+++ b/metadata/updater/updater.go
@@ -218,7 +218,7 @@ func (update *Updater) DownloadTarget(targetFile *metadata.TargetFiles, filePath
 	}
 	if targetBaseURL == "" {
 		if update.cfg.RemoteTargetsURL == "" {
-			return "", nil, metadata.ErrValue{Msg: "targetBaseURL must be set in either DownloadTarget() or the Updater struct"}
+			return "", nil, &metadata.ErrValue{Msg: "targetBaseURL must be set in either DownloadTarget() or the Updater struct"}
 		}
 		targetBaseURL = ensureTrailingSlash(update.cfg.RemoteTargetsURL)
 	} else {
@@ -308,7 +308,7 @@ func (update *Updater) loadTimestamp() error {
 		// local timestamp exists, let's try to verify it and load it to the trusted metadata set
 		_, err := update.trusted.UpdateTimestamp(data)
 		if err != nil {
-			if errors.Is(err, metadata.ErrRepository{}) {
+			if errors.Is(err, &metadata.ErrRepository{}) {
 				// local timestamp is not valid, proceed downloading from remote; note that this error type includes several other subset errors
 				log.Info("Local timestamp is not valid")
 			} else {
@@ -327,7 +327,7 @@ func (update *Updater) loadTimestamp() error {
 	// try to verify and load the newly downloaded timestamp
 	_, err = update.trusted.UpdateTimestamp(data)
 	if err != nil {
-		if errors.Is(err, metadata.ErrEqualVersionNumber{}) {
+		if errors.Is(err, &metadata.ErrEqualVersionNumber{}) {
 			// if the new timestamp version is the same as current, discard the
 			// new timestamp; this is normal and it shouldn't raise any error
 			return nil
@@ -357,7 +357,7 @@ func (update *Updater) loadSnapshot() error {
 		_, err = update.trusted.UpdateSnapshot(data, true)
 		if err != nil {
 			// this means snapshot verification/loading failed
-			if errors.Is(err, metadata.ErrRepository{}) {
+			if errors.Is(err, &metadata.ErrRepository{}) {
 				// local snapshot is not valid, proceed downloading from remote; note that this error type includes several other subset errors
 				log.Info("Local snapshot is not valid")
 			} else {
@@ -423,7 +423,7 @@ func (update *Updater) loadTargets(roleName, parentName string) (*metadata.Metad
 		delegatedTargets, err := update.trusted.UpdateDelegatedTargets(data, roleName, parentName)
 		if err != nil {
 			// this means targets verification/loading failed
-			if errors.Is(err, metadata.ErrRepository{}) {
+			if errors.Is(err, &metadata.ErrRepository{}) {
 				// local target file is not valid, proceed downloading from remote; note that this error type includes several other subset errors
 				log.Info("Local role is not valid", "role", roleName)
 			} else {
@@ -484,7 +484,7 @@ func (update *Updater) loadRoot() error {
 		data, err := update.downloadMetadata(metadata.ROOT, update.cfg.RootMaxLength, strconv.FormatInt(nextVersion, 10))
 		if err != nil {
 			// downloading the root metadata failed for some reason
-			var tmpErr metadata.ErrDownloadHTTP
+			var tmpErr *metadata.ErrDownloadHTTP
 			if errors.As(err, &tmpErr) {
 				if tmpErr.StatusCode != http.StatusNotFound && tmpErr.StatusCode != http.StatusForbidden {
 					// unexpected HTTP status code
@@ -674,7 +674,7 @@ func (update *Updater) downloadMetadata(roleName string, length int64, version s
 func (update *Updater) generateTargetFilePath(tf *metadata.TargetFiles) (string, error) {
 	// LocalTargetsDir can be omitted if caching is disabled
 	if update.cfg.LocalTargetsDir == "" && !update.cfg.DisableLocalCache {
-		return "", metadata.ErrValue{Msg: "LocalTargetsDir must be set if filepath is not given"}
+		return "", &metadata.ErrValue{Msg: "LocalTargetsDir must be set if filepath is not given"}
 	}
 	// Use URL encoded target path as filename
 	return url.JoinPath(update.cfg.LocalTargetsDir, url.QueryEscape(tf.Path))


Test patch:
diff --git a/metadata/fetcher/fetcher_test.go b/metadata/fetcher/fetcher_test.go
index 484ebd0..5bd8e6d 100644
--- a/metadata/fetcher/fetcher_test.go
+++ b/metadata/fetcher/fetcher_test.go
@@ -64,7 +64,7 @@ func TestDownLoadFile(t *testing.T) {
 			desc:    "Path does not exist",
 			url:     "https://jku.github.io/tuf-demo/metadata/badPath.json",
 			data:    nil,
-			wantErr: metadata.ErrDownloadHTTP{},
+			wantErr: &metadata.ErrDownloadHTTP{},
 		},
 		{
 			name:      "data too long",
@@ -72,7 +72,7 @@ func TestDownLoadFile(t *testing.T) {
 			url:       "https://jku.github.io/tuf-demo/metadata/1.root.json",
 			maxLength: 1,
 			data:      nil,
-			wantErr:   metadata.ErrDownloadLengthMismatch{},
+			wantErr:   &metadata.ErrDownloadLengthMismatch{},
 		},
 	} {
 		t.Run(tt.name, func(t *testing.T) {
diff --git a/metadata/metadata_api_test.go b/metadata/metadata_api_test.go
index 38950a8..2ab6b9d 100644
--- a/metadata/metadata_api_test.go
+++ b/metadata/metadata_api_test.go
@@ -56,13 +56,13 @@ func TestGenericRead(t *testing.T) {
 	// Assert that it chokes correctly on an unknown metadata type
 	badMetadata := "{\"signed\": {\"_type\": \"bad-metadata\"}}"
 	_, err := Root().FromBytes([]byte(badMetadata))
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type root, got - bad-metadata"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type root, got - bad-metadata"})
 	_, err = Snapshot().FromBytes([]byte(badMetadata))
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type snapshot, got - bad-metadata"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type snapshot, got - bad-metadata"})
 	_, err = Targets().FromBytes([]byte(badMetadata))
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type targets, got - bad-metadata"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type targets, got - bad-metadata"})
 	_, err = Timestamp().FromBytes([]byte(badMetadata))
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type timestamp, got - bad-metadata"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type timestamp, got - bad-metadata"})
 
 	badMetadataPath := filepath.Join(testutils.RepoDir, "bad-metadata.json")
 	err = os.WriteFile(badMetadataPath, []byte(badMetadata), 0644)
@@ -70,13 +70,13 @@ func TestGenericRead(t *testing.T) {
 	assert.FileExists(t, badMetadataPath)
 
 	_, err = Root().FromFile(badMetadataPath)
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type root, got - bad-metadata"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type root, got - bad-metadata"})
 	_, err = Snapshot().FromFile(badMetadataPath)
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type snapshot, got - bad-metadata"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type snapshot, got - bad-metadata"})
 	_, err = Targets().FromFile(badMetadataPath)
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type targets, got - bad-metadata"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type targets, got - bad-metadata"})
 	_, err = Timestamp().FromFile(badMetadataPath)
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type timestamp, got - bad-metadata"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type timestamp, got - bad-metadata"})
 
 	err = os.RemoveAll(badMetadataPath)
 	assert.NoError(t, err)
@@ -86,35 +86,35 @@ func TestGenericRead(t *testing.T) {
 func TestGenericReadFromMismatchingRoles(t *testing.T) {
 	// Test failing to load other roles from root metadata
 	_, err := Snapshot().FromFile(filepath.Join(testutils.RepoDir, "root.json"))
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type snapshot, got - root"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type snapshot, got - root"})
 	_, err = Timestamp().FromFile(filepath.Join(testutils.RepoDir, "root.json"))
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type timestamp, got - root"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type timestamp, got - root"})
 	_, err = Targets().FromFile(filepath.Join(testutils.RepoDir, "root.json"))
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type targets, got - root"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type targets, got - root"})
 
 	// Test failing to load other roles from targets metadata
 	_, err = Snapshot().FromFile(filepath.Join(testutils.RepoDir, "targets.json"))
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type snapshot, got - targets"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type snapshot, got - targets"})
 	_, err = Timestamp().FromFile(filepath.Join(testutils.RepoDir, "targets.json"))
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type timestamp, got - targets"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type timestamp, got - targets"})
 	_, err = Root().FromFile(filepath.Join(testutils.RepoDir, "targets.json"))
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type root, got - targets"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type root, got - targets"})
 
 	// Test failing to load other roles from timestamp metadata
 	_, err = Snapshot().FromFile(filepath.Join(testutils.RepoDir, "timestamp.json"))
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type snapshot, got - timestamp"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type snapshot, got - timestamp"})
 	_, err = Targets().FromFile(filepath.Join(testutils.RepoDir, "timestamp.json"))
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type targets, got - timestamp"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type targets, got - timestamp"})
 	_, err = Root().FromFile(filepath.Join(testutils.RepoDir, "timestamp.json"))
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type root, got - timestamp"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type root, got - timestamp"})
 
 	// Test failing to load other roles from snapshot metadata
 	_, err = Targets().FromFile(filepath.Join(testutils.RepoDir, "snapshot.json"))
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type targets, got - snapshot"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type targets, got - snapshot"})
 	_, err = Timestamp().FromFile(filepath.Join(testutils.RepoDir, "snapshot.json"))
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type timestamp, got - snapshot"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type timestamp, got - snapshot"})
 	_, err = Root().FromFile(filepath.Join(testutils.RepoDir, "snapshot.json"))
-	assert.ErrorIs(t, err, ErrValue{"expected metadata type root, got - snapshot"})
+	assert.ErrorIs(t, err, &ErrValue{"expected metadata type root, got - snapshot"})
 }
 
 func TestMDReadWriteFileExceptions(t *testing.T) {
@@ -534,21 +534,21 @@ func TestMetadataVerifyDelegate(t *testing.T) {
 
 	// Only root and targets can verify delegates
 	err = snapshot.VerifyDelegate(SNAPSHOT, snapshot)
-	assert.ErrorIs(t, err, ErrType{"call is valid only on delegator metadata (should be either root or targets)"})
+	assert.ErrorIs(t, err, &ErrType{"call is valid only on delegator metadata (should be either root or targets)"})
 	// Verify fails for roles that are not delegated by delegator
 	err = root.VerifyDelegate("role1", role1)
-	assert.ErrorIs(t, err, ErrValue{"no delegation found for role1"})
+	assert.ErrorIs(t, err, &ErrValue{"no delegation found for role1"})
 	err = targets.VerifyDelegate(TARGETS, targets)
-	assert.ErrorIs(t, err, ErrValue{"no delegation found for targets"})
+	assert.ErrorIs(t, err, &ErrValue{"no delegation found for targets"})
 	// Verify fails when delegator has no delegations
 	err = role2.VerifyDelegate("role1", role1)
-	assert.ErrorIs(t, err, ErrValue{"no delegations found"})
+	assert.ErrorIs(t, err, &ErrValue{"no delegations found"})
 
 	// Verify fails when delegate content is modified
 	expires := snapshot.Signed.Expires
 	snapshot.Signed.Expires = snapshot.Signed.Expires.Add(time.Hour * 24)
 	err = root.VerifyDelegate(SNAPSHOT, snapshot)
-	assert.ErrorIs(t, err, ErrUnsignedMetadata{"Verifying snapshot failed, not enough signatures, got 0, want 1"})
+	assert.ErrorIs(t, err, &ErrUnsignedMetadata{"Verifying snapshot failed, not enough signatures, got 0, want 1"})
 	snapshot.Signed.Expires = expires
 
 	// Verify fails with verification error
@@ -558,12 +558,12 @@ func TestMetadataVerifyDelegate(t *testing.T) {
 	assert.NotEmpty(t, goodSig)
 	snapshot.Signatures[idx].Signature = []byte("foo")
 	err = root.VerifyDelegate(SNAPSHOT, snapshot)
-	assert.ErrorIs(t, err, ErrUnsignedMetadata{"Verifying snapshot failed, not enough signatures, got 0, want 1"})
+	assert.ErrorIs(t, err, &ErrUnsignedMetadata{"Verifying snapshot failed, not enough signatures, got 0, want 1"})
 	snapshot.Signatures[idx].Signature = goodSig
 
 	// Verify fails if roles keys do not sign the metadata
 	err = root.VerifyDelegate(TIMESTAMP, snapshot)
-	assert.ErrorIs(t, err, ErrUnsignedMetadata{"Verifying timestamp failed, not enough signatures, got 0, want 1"})
+	assert.ErrorIs(t, err, &ErrUnsignedMetadata{"Verifying timestamp failed, not enough signatures, got 0, want 1"})
 
 	// Add a key to snapshot role, make sure the new sig fails to verify
 	tsKeyID := root.Signed.Roles[TIMESTAMP].KeyIDs[0]
@@ -583,7 +583,7 @@ func TestMetadataVerifyDelegate(t *testing.T) {
 	// Verify fails if threshold of signatures is not reached
 	root.Signed.Roles[SNAPSHOT].Threshold = 2
 	err = root.VerifyDelegate(SNAPSHOT, snapshot)
-	assert.ErrorIs(t, err, ErrUnsignedMetadata{"Verifying snapshot failed, not enough signatures, got 1, want 2"})
+	assert.ErrorIs(t, err, &ErrUnsignedMetadata{"Verifying snapshot failed, not enough signatures, got 1, want 2"})
 
 	// Verify succeeds when we correct the new signature and reach the
 	// threshold of 2 keys
@@ -637,7 +637,7 @@ func TestRootAddKeyAndRevokeKey(t *testing.T) {
 
 	// Add the same key to a nonexistent role.
 	err = root.Signed.AddKey(rootKey2, "nosuchrole")
-	assert.ErrorIs(t, err, ErrValue{"role nosuchrole doesn't exist"})
+	assert.ErrorIs(t, err, &ErrValue{"role nosuchrole doesn't exist"})
 
 	// Remove the key from root role (targets role still uses it)
 	err = root.Signed.RevokeKey(rootKey2.id, ROOT)
@@ -652,9 +652,9 @@ func TestRootAddKeyAndRevokeKey(t *testing.T) {
 	assert.NotContains(t, root.Signed.Keys, rootKey2.id)
 
 	err = root.Signed.RevokeKey("nosuchkey", ROOT)
-	assert.ErrorIs(t, err, ErrValue{"key with id nosuchkey is not used by root"})
+	assert.ErrorIs(t, err, &ErrValue{"key with id nosuchkey is not used by root"})
 	err = root.Signed.RevokeKey(rootKey2.id, "nosuchrole")
-	assert.ErrorIs(t, err, ErrValue{"role nosuchrole doesn't exist"})
+	assert.ErrorIs(t, err, &ErrValue{"role nosuchrole doesn't exist"})
 }
 
 func TestTargetsKeyAPI(t *testing.T) {
@@ -694,7 +694,7 @@ func TestTargetsKeyAPI(t *testing.T) {
 
 	// Try adding a key to a delegated role that doesn't exists
 	err = targets.Signed.AddKey(key, "nosuchrole")
-	assert.ErrorIs(t, err, ErrValue{"delegated role nosuchrole doesn't exist"})
+	assert.ErrorIs(t, err, &ErrValue{"delegated role nosuchrole doesn't exist"})
 
 	//  Add the same key to "role2" as well
 	err = targets.Signed.AddKey(key, "role2")
@@ -717,11 +717,11 @@ func TestTargetsKeyAPI(t *testing.T) {
 
 	// Try remove key not used by "role1"
 	err = targets.Signed.RevokeKey(key.id, "role1")
-	assert.ErrorIs(t, err, ErrValue{fmt.Sprintf("key with id %s is not used by role1", key.id)})
+	assert.ErrorIs(t, err, &ErrValue{fmt.Sprintf("key with id %s is not used by role1", key.id)})
 
 	// Try removing a key from delegated role that doesn't exists
 	err = targets.Signed.RevokeKey(key.id, "nosuchrole")
-	assert.ErrorIs(t, err, ErrValue{"delegated role nosuchrole doesn't exist"})
+	assert.ErrorIs(t, err, &ErrValue{"delegated role nosuchrole doesn't exist"})
 
 	// Remove delegations as a whole
 	targets.Signed.Delegations = nil
@@ -729,9 +729,9 @@ func TestTargetsKeyAPI(t *testing.T) {
 	//Test that calling add_key and revoke_key throws an error
 	// and that delegations is still None after each of the api calls
 	err = targets.Signed.AddKey(key, "role1")
-	assert.ErrorIs(t, err, ErrValue{"delegated role role1 doesn't exist"})
+	assert.ErrorIs(t, err, &ErrValue{"delegated role role1 doesn't exist"})
 	err = targets.Signed.RevokeKey(key.id, "role1")
-	assert.ErrorIs(t, err, ErrValue{"delegated role role1 doesn't exist"})
+	assert.ErrorIs(t, err, &ErrValue{"delegated role role1 doesn't exist"})
 	assert.Nil(t, targets.Signed.Delegations)
 }
 
@@ -781,7 +781,7 @@ func TestTargetsKeyAPIWithSuccinctRoles(t *testing.T) {
 
 	// Try removing it again.
 	err = targets.Signed.RevokeKey(key.id, "foo")
-	assert.ErrorIs(t, err, ErrValue{fmt.Sprintf("key with id %s is not used by SuccinctRoles", key.id)})
+	assert.ErrorIs(t, err, &ErrValue{fmt.Sprintf("key with id %s is not used by SuccinctRoles", key.id)})
 }
 
 func TestLengthAndHashValidation(t *testing.T) {
@@ -813,18 +813,18 @@ func TestLengthAndHashValidation(t *testing.T) {
 	originalLength := snapshotMetafile.Length
 	snapshotMetafile.Length = 2345
 	err = snapshotMetafile.VerifyLengthHashes(data)
-	assert.ErrorIs(t, err, ErrLengthOrHashMismatch{fmt.Sprintf("length verification failed - expected %d, got %d", 2345, originalLength)})
+	assert.ErrorIs(t, err, &ErrLengthOrHashMismatch{fmt.Sprintf("length verification failed - expected %d, got %d", 2345, originalLength)})
 
 	snapshotMetafile.Length = originalLength
 	originalHashSHA256 := snapshotMetafile.Hashes["sha256"]
 	snapshotMetafile.Hashes["sha256"] = []byte("incorrecthash")
 	err = snapshotMetafile.VerifyLengthHashes(data)
-	assert.ErrorIs(t, err, ErrLengthOrHashMismatch{"hash verification failed - mismatch for algorithm sha256"})
+	assert.ErrorIs(t, err, &ErrLengthOrHashMismatch{"hash verification failed - mismatch for algorithm sha256"})
 
 	snapshotMetafile.Hashes["sha256"] = originalHashSHA256
 	snapshotMetafile.Hashes["unsupported-alg"] = []byte("72c5cabeb3e8079545a5f4d2b067f8e35f18a0de3c2b00d3cb8d05919c19c72d")
 	err = snapshotMetafile.VerifyLengthHashes(data)
-	assert.ErrorIs(t, err, ErrLengthOrHashMismatch{"hash verification failed - unknown hashing algorithm - unsupported-alg"})
+	assert.ErrorIs(t, err, &ErrLengthOrHashMismatch{"hash verification failed - unknown hashing algorithm - unsupported-alg"})
 
 	// test optional length and hashes
 	snapshotMetafile.Length = 0
@@ -843,12 +843,12 @@ func TestLengthAndHashValidation(t *testing.T) {
 	originalLength = targetFile.Length
 	targetFile.Length = 2345
 	err = targetFile.VerifyLengthHashes(targetFileData)
-	assert.ErrorIs(t, err, ErrLengthOrHashMismatch{fmt.Sprintf("length verification failed - expected %d, got %d", 2345, originalLength)})
+	assert.ErrorIs(t, err, &ErrLengthOrHashMismatch{fmt.Sprintf("length verification failed - expected %d, got %d", 2345, originalLength)})
 
 	targetFile.Length = originalLength
 	targetFile.Hashes["sha256"] = []byte("incorrecthash")
 	err = targetFile.VerifyLengthHashes(targetFileData)
-	assert.ErrorIs(t, err, ErrLengthOrHashMismatch{"hash verification failed - mismatch for algorithm sha256"})
+	assert.ErrorIs(t, err, &ErrLengthOrHashMismatch{"hash verification failed - mismatch for algorithm sha256"})
 }
 
 func TestTargetFileFromFile(t *testing.T) {
@@ -866,11 +866,11 @@ func TestTargetFileFromFile(t *testing.T) {
 	mismatchingTargetFileData, err := os.ReadFile(mismatchingTargetFilePath)
 	assert.NoError(t, err)
 	err = targetFileFromFile.VerifyLengthHashes(mismatchingTargetFileData)
-	assert.ErrorIs(t, err, ErrLengthOrHashMismatch{"hash verification failed - mismatch for algorithm sha256"})
+	assert.ErrorIs(t, err, &ErrLengthOrHashMismatch{"hash verification failed - mismatch for algorithm sha256"})
 
 	// Test with an unsupported algorithm
 	_, err = TargetFile().FromFile(targetFilePath, "123")
-	assert.ErrorIs(t, err, ErrValue{"failed generating TargetFile - unsupported hashing algorithm - 123"})
+	assert.ErrorIs(t, err, &ErrValue{"failed generating TargetFile - unsupported hashing algorithm - 123"})
 }
 
 func TestTargetFileCustom(t *testing.T) {
diff --git a/metadata/trustedmetadata/trustedmetadata_test.go b/metadata/trustedmetadata/trustedmetadata_test.go
index aeb21e1..75d7d3b 100644
--- a/metadata/trustedmetadata/trustedmetadata_test.go
+++ b/metadata/trustedmetadata/trustedmetadata_test.go
@@ -223,36 +223,36 @@ func TestOutOfOrderOps(t *testing.T) {
 
 	//  Update snapshot before timestamp
 	_, err = trustedSet.UpdateSnapshot(allRoles[metadata.SNAPSHOT], false)
-	assert.ErrorIs(t, err, metadata.ErrRuntime{Msg: "cannot update snapshot before timestamp"})
+	assert.ErrorIs(t, err, &metadata.ErrRuntime{Msg: "cannot update snapshot before timestamp"})
 
 	_, err = trustedSet.UpdateTimestamp(allRoles[metadata.TIMESTAMP])
 	assert.NoError(t, err)
 
 	// Update root after timestamp
 	_, err = trustedSet.UpdateRoot(allRoles[metadata.ROOT])
-	assert.ErrorIs(t, err, metadata.ErrRuntime{Msg: "cannot update root after timestamp"})
+	assert.ErrorIs(t, err, &metadata.ErrRuntime{Msg: "cannot update root after timestamp"})
 
 	// Update targets before snapshot
 	_, err = trustedSet.UpdateTargets(allRoles[metadata.TARGETS])
-	assert.ErrorIs(t, err, metadata.ErrRuntime{Msg: "cannot load targets before snapshot"})
+	assert.ErrorIs(t, err, &metadata.ErrRuntime{Msg: "cannot load targets before snapshot"})
 
 	_, err = trustedSet.UpdateSnapshot(allRoles[metadata.SNAPSHOT], false)
 	assert.NoError(t, err)
 
 	// Update timestamp after snapshot
 	_, err = trustedSet.UpdateTimestamp(allRoles[metadata.TIMESTAMP])
-	assert.ErrorIs(t, err, metadata.ErrRuntime{Msg: "cannot update timestamp after snapshot"})
+	assert.ErrorIs(t, err, &metadata.ErrRuntime{Msg: "cannot update timestamp after snapshot"})
 
 	// Update delegated targets before targets
 	_, err = trustedSet.UpdateDelegatedTargets(allRoles["role1"], "role1", metadata.TARGETS)
-	assert.ErrorIs(t, err, metadata.ErrRuntime{Msg: "cannot load targets before delegator"})
+	assert.ErrorIs(t, err, &metadata.ErrRuntime{Msg: "cannot load targets before delegator"})
 
 	_, err = trustedSet.UpdateTargets(allRoles[metadata.TARGETS])
 	assert.NoError(t, err)
 
 	//  Update snapshot after sucessful targets update
 	_, err = trustedSet.UpdateSnapshot(allRoles[metadata.SNAPSHOT], false)
-	assert.ErrorIs(t, err, metadata.ErrRuntime{Msg: "cannot update snapshot after targets"})
+	assert.ErrorIs(t, err, &metadata.ErrRuntime{Msg: "cannot update snapshot after targets"})
 
 	_, err = trustedSet.UpdateDelegatedTargets(allRoles["role1"], "role1", metadata.TARGETS)
 	assert.NoError(t, err)
@@ -275,11 +275,11 @@ func TestRootWithInvalidJson(t *testing.T) {
 	rootBytes, err := root.ToBytes(true)
 	assert.NoError(t, err)
 	_, err = trustedSet.UpdateRoot(rootBytes)
-	assert.ErrorIs(t, err, metadata.ErrUnsignedMetadata{Msg: "Verifying root failed, not enough signatures, got 0, want 1"})
+	assert.ErrorIs(t, err, &metadata.ErrUnsignedMetadata{Msg: "Verifying root failed, not enough signatures, got 0, want 1"})
 
 	// metadata is of wrong type
 	_, err = trustedSet.UpdateRoot(allRoles[metadata.SNAPSHOT])
-	assert.ErrorIs(t, err, metadata.ErrValue{Msg: "expected metadata type root, got - snapshot"})
+	assert.ErrorIs(t, err, &metadata.ErrValue{Msg: "expected metadata type root, got - snapshot"})
 }
 
 func TestTopLevelMetadataWithInvalidJSON(t *testing.T) {
@@ -300,11 +300,11 @@ func TestTopLevelMetadataWithInvalidJSON(t *testing.T) {
 	timestampBytes, err := timestamp.ToBytes(true)
 	assert.NoError(t, err)
 	_, err = trustedSet.UpdateTimestamp(timestampBytes)
-	assert.ErrorIs(t, err, metadata.ErrUnsignedMetadata{Msg: "Verifying timestamp failed, not enough signatures, got 0, want 1"})
+	assert.ErrorIs(t, err, &metadata.ErrUnsignedMetadata{Msg: "Verifying timestamp failed, not enough signatures, got 0, want 1"})
 
 	// timestamp is of wrong type
 	_, err = trustedSet.UpdateTimestamp(allRoles[metadata.ROOT])
-	assert.ErrorIs(t, err, metadata.ErrValue{Msg: "expected metadata type timestamp, got - root"})
+	assert.ErrorIs(t, err, &metadata.ErrValue{Msg: "expected metadata type timestamp, got - root"})
 
 	// SNAPSHOT
 	_, err = trustedSet.UpdateTimestamp(properTimestampBytes)
@@ -322,11 +322,11 @@ func TestTopLevelMetadataWithInvalidJSON(t *testing.T) {
 	snapshotBytes, err := snapshot.ToBytes(true)
 	assert.NoError(t, err)
 	_, err = trustedSet.UpdateSnapshot(snapshotBytes, false)
-	assert.ErrorIs(t, err, metadata.ErrUnsignedMetadata{Msg: "Verifying snapshot failed, not enough signatures, got 0, want 1"})
+	assert.ErrorIs(t, err, &metadata.ErrUnsignedMetadata{Msg: "Verifying snapshot failed, not enough signatures, got 0, want 1"})
 
 	// snapshot is of wrong type
 	_, err = trustedSet.UpdateSnapshot(allRoles[metadata.ROOT], false)
-	assert.ErrorIs(t, err, metadata.ErrValue{Msg: "expected metadata type snapshot, got - root"})
+	assert.ErrorIs(t, err, &metadata.ErrValue{Msg: "expected metadata type snapshot, got - root"})
 
 	// TARGETS
 	_, err = trustedSet.UpdateSnapshot(properSnapshotBytes, false)
@@ -342,11 +342,11 @@ func TestTopLevelMetadataWithInvalidJSON(t *testing.T) {
 	targetsBytes, err := targets.ToBytes(true)
 	assert.NoError(t, err)
 	_, err = trustedSet.UpdateTargets(targetsBytes)
-	assert.ErrorIs(t, err, metadata.ErrUnsignedMetadata{Msg: "Verifying targets failed, not enough signatures, got 0, want 1"})
+	assert.ErrorIs(t, err, &metadata.ErrUnsignedMetadata{Msg: "Verifying targets failed, not enough signatures, got 0, want 1"})
 
 	// targets is of wrong type
 	_, err = trustedSet.UpdateTargets(allRoles[metadata.ROOT])
-	assert.ErrorIs(t, err, metadata.ErrValue{Msg: "expected metadata type targets, got - root"})
+	assert.ErrorIs(t, err, &metadata.ErrValue{Msg: "expected metadata type targets, got - root"})
 }
 
 func TestUpdateRootNewRoot(t *testing.T) {
@@ -376,7 +376,7 @@ func TestUpdateRootNewRootFailTreshholdVerification(t *testing.T) {
 	trustedSet, err := New(allRoles[metadata.ROOT])
 	assert.NoError(t, err)
 	_, err = trustedSet.UpdateRoot(root)
-	assert.ErrorIs(t, err, metadata.ErrUnsignedMetadata{Msg: "Verifying root failed, not enough signatures, got 1, want 2"})
+	assert.ErrorIs(t, err, &metadata.ErrUnsignedMetadata{Msg: "Verifying root failed, not enough signatures, got 1, want 2"})
 }
 
 func TestUpdateRootNewRootVerSameAsTrustedRootVer(t *testing.T) {
@@ -384,7 +384,7 @@ func TestUpdateRootNewRootVerSameAsTrustedRootVer(t *testing.T) {
 	assert.NoError(t, err)
 
 	_, err = trustedSet.UpdateRoot(allRoles[metadata.ROOT])
-	assert.ErrorIs(t, err, metadata.ErrBadVersionNumber{Msg: "bad version number, expected 2, got 1"})
+	assert.ErrorIs(t, err, &metadata.ErrBadVersionNumber{Msg: "bad version number, expected 2, got 1"})
 }
 
 func TestRootExpiredFinalRoot(t *testing.T) {
@@ -401,7 +401,7 @@ func TestRootExpiredFinalRoot(t *testing.T) {
 
 	// Update timestamp to trigger final root expiry check
 	_, err = trustedSet.UpdateTimestamp(allRoles[metadata.TIMESTAMP])
-	assert.ErrorIs(t, err, metadata.ErrExpiredMetadata{Msg: "final root.json is expired"})
+	assert.ErrorIs(t, err, &metadata.ErrExpiredMetadata{Msg: "final root.json is expired"})
 }
 
 func TestUpdateTimestampNewTimestampVerBelowTrustedVer(t *testing.T) {
@@ -417,7 +417,7 @@ func TestUpdateTimestampNewTimestampVerBelowTrustedVer(t *testing.T) {
 	_, err = trustedSet.UpdateTimestamp(timestamp)
 	assert.NoError(t, err)
 	_, err = trustedSet.UpdateTimestamp(allRoles[metadata.TIMESTAMP])
-	assert.ErrorIs(t, err, metadata.ErrBadVersionNumber{Msg: "new timestamp version 1 must be >= 3"})
+	assert.ErrorIs(t, err, &metadata.ErrBadVersionNumber{Msg: "new timestamp version 1 must be >= 3"})
 }
 
 func TestUpdateTimestampWithSameTimestamp(t *testing.T) {
@@ -432,7 +432,7 @@ func TestUpdateTimestampWithSameTimestamp(t *testing.T) {
 	// Update timestamp with the same version.
 	_, err = trustedSet.UpdateTimestamp(allRoles[metadata.TIMESTAMP])
 	// EqualVersionNumberError
-	assert.ErrorIs(t, err, metadata.ErrEqualVersionNumber{Msg: "new timestamp version 1 equals the old one 1"})
+	assert.ErrorIs(t, err, &metadata.ErrEqualVersionNumber{Msg: "new timestamp version 1 equals the old one 1"})
 
 	// Verify that the timestamp object was not updated.
 	assert.Equal(t, initialTimestamp, trustedSet.Timestamp)
@@ -454,7 +454,7 @@ func TestUpdateTimestampSnapshotCerBellowCurrent(t *testing.T) {
 
 	// new timestamp meta version < trusted timestamp meta version
 	_, err = trustedSet.UpdateTimestamp(allRoles[metadata.TIMESTAMP])
-	assert.ErrorIs(t, err, metadata.ErrBadVersionNumber{Msg: "new timestamp version 1 must be >= 2"})
+	assert.ErrorIs(t, err, &metadata.ErrBadVersionNumber{Msg: "new timestamp version 1 must be >= 2"})
 }
 
 func TestUpdateTimestampExpired(t *testing.T) {
@@ -468,9 +468,9 @@ func TestUpdateTimestampExpired(t *testing.T) {
 	trustedSet, err := New(allRoles[metadata.ROOT])
 	assert.NoError(t, err)
 	_, err = trustedSet.UpdateTimestamp(timestamp)
-	assert.ErrorIs(t, err, metadata.ErrExpiredMetadata{Msg: "timestamp.json is expired"})
+	assert.ErrorIs(t, err, &metadata.ErrExpiredMetadata{Msg: "timestamp.json is expired"})
 	_, err = trustedSet.UpdateSnapshot(allRoles[metadata.SNAPSHOT], false)
-	assert.ErrorIs(t, err, metadata.ErrExpiredMetadata{Msg: "timestamp.json is expired"})
+	assert.ErrorIs(t, err, &metadata.ErrExpiredMetadata{Msg: "timestamp.json is expired"})
 }
 
 func TestUpdateSnapshotLengthOrHashMismatch(t *testing.T) {
@@ -485,7 +485,7 @@ func TestUpdateSnapshotLengthOrHashMismatch(t *testing.T) {
 	_, err = trustedSet.UpdateTimestamp(timestamp)
 	assert.NoError(t, err)
 	_, err = trustedSet.UpdateSnapshot(allRoles[metadata.SNAPSHOT], false)
-	assert.ErrorIs(t, err, metadata.ErrLengthOrHashMismatch{Msg: "length verification failed - expected 1, got 652"})
+	assert.ErrorIs(t, err, &metadata.ErrLengthOrHashMismatch{Msg: "length verification failed - expected 1, got 652"})
 }
 
 func TestUpdateSnapshotFailThreshholdVerification(t *testing.T) {
@@ -500,7 +500,7 @@ func TestUpdateSnapshotFailThreshholdVerification(t *testing.T) {
 	snapshotBytes, err := snapshot.ToBytes(true)
 	assert.NoError(t, err)
 	_, err = trustedSet.UpdateSnapshot(snapshotBytes, false)
-	assert.ErrorIs(t, err, metadata.ErrUnsignedMetadata{Msg: "Verifying snapshot failed, not enough signatures, got 0, want 1"})
+	assert.ErrorIs(t, err, &metadata.ErrUnsignedMetadata{Msg: "Verifying snapshot failed, not enough signatures, got 0, want 1"})
 }
 
 func TestUpdateSnapshotVersionDivergeTimestampSnapshotVersion(t *testing.T) {
@@ -516,11 +516,11 @@ func TestUpdateSnapshotVersionDivergeTimestampSnapshotVersion(t *testing.T) {
 
 	// If intermediate snapshot version is incorrect, load it but also raise
 	_, err = trustedSet.UpdateSnapshot(allRoles[metadata.SNAPSHOT], false)
-	assert.ErrorIs(t, err, metadata.ErrBadVersionNumber{Msg: "expected 2, got 1"})
+	assert.ErrorIs(t, err, &metadata.ErrBadVersionNumber{Msg: "expected 2, got 1"})
 
 	// Targets update starts but fails if snapshot version does not match
 	_, err = trustedSet.UpdateTargets(allRoles[metadata.TARGETS])
-	assert.ErrorIs(t, err, metadata.ErrBadVersionNumber{Msg: "expected 2, got 1"})
+	assert.ErrorIs(t, err, &metadata.ErrBadVersionNumber{Msg: "expected 2, got 1"})
 }
 
 // Update all metadata roles besides targets.
@@ -554,7 +554,7 @@ func TestUpdateSnapshotFileRemovedFromMeta(t *testing.T) {
 	snapshot, err := modifySnapshotMetadata(removeFileFromMeta)
 	assert.NoError(t, err)
 	_, err = trustedSet.UpdateSnapshot(snapshot, false)
-	assert.ErrorIs(t, err, metadata.ErrRepository{Msg: "new snapshot is missing info for targets.json"})
+	assert.ErrorIs(t, err, &metadata.ErrRepository{Msg: "new snapshot is missing info for targets.json"})
 }
 
 func TestUpdateSnapshotMetaVersionDecreases(t *testing.T) {
@@ -572,7 +572,7 @@ func TestUpdateSnapshotMetaVersionDecreases(t *testing.T) {
 	assert.NoError(t, err)
 
 	_, err = trustedSet.UpdateSnapshot(allRoles[metadata.SNAPSHOT], false)
-	assert.ErrorIs(t, err, metadata.ErrBadVersionNumber{Msg: "expected targets.json version 1, got 2"})
+	assert.ErrorIs(t, err, &metadata.ErrBadVersionNumber{Msg: "expected targets.json version 1, got 2"})
 }
 
 func TestUpdateSnapshotExpiredNewSnapshot(t *testing.T) {
@@ -589,11 +589,11 @@ func TestUpdateSnapshotExpiredNewSnapshot(t *testing.T) {
 	assert.NoError(t, err)
 
 	_, err = trustedSet.UpdateSnapshot(snapshot, false)
-	assert.ErrorIs(t, err, metadata.ErrExpiredMetadata{Msg: "snapshot.json is expired"})
+	assert.ErrorIs(t, err, &metadata.ErrExpiredMetadata{Msg: "snapshot.json is expired"})
 
 	// Targets update does start but fails because snapshot is expired
 	_, err = trustedSet.UpdateTargets(allRoles[metadata.TARGETS])
-	assert.ErrorIs(t, err, metadata.ErrExpiredMetadata{Msg: "snapshot.json is expired"})
+	assert.ErrorIs(t, err, &metadata.ErrExpiredMetadata{Msg: "snapshot.json is expired"})
 
 }
 
@@ -617,7 +617,7 @@ func TestUpdateSnapshotSuccessfulRollbackChecks(t *testing.T) {
 	// Load a "local" snapshot with mismatching version (loading happens but
 	// ErrBadVersionNumber is raised), then update to newer one:
 	_, err = trustedSet.UpdateSnapshot(allRoles[metadata.SNAPSHOT], false)
-	assert.ErrorIs(t, err, metadata.ErrBadVersionNumber{Msg: "expected 2, got 1"})
+	assert.ErrorIs(t, err, &metadata.ErrBadVersionNumber{Msg: "expected 2, got 1"})
 
 	bumpVersion := func(snapahot *metadata.Metadata[metadata.SnapshotType]) {
 		snapahot.Signed.Version += 1
@@ -647,7 +647,7 @@ func TestUpdateTargetsMoMetaInSnapshot(t *testing.T) {
 
 	// Remove meta information with information about targets from snapshot
 	_, err = trustedSet.UpdateTargets(allRoles[metadata.TARGETS])
-	assert.ErrorIs(t, err, metadata.ErrRepository{Msg: "snapshot does not contain information for targets"})
+	assert.ErrorIs(t, err, &metadata.ErrRepository{Msg: "snapshot does not contain information for targets"})
 
 }
 
@@ -669,7 +669,7 @@ func TestUpdateTargetsHashDiverfeFromSnapshotMetaHash(t *testing.T) {
 
 	// Observed hash != stored hash in snapshot meta for targets
 	_, err = trustedSet.UpdateTargets(allRoles[metadata.TARGETS])
-	assert.ErrorIs(t, err, metadata.ErrLengthOrHashMismatch{Msg: "length verification failed - expected 1, got 1266"})
+	assert.ErrorIs(t, err, &metadata.ErrLengthOrHashMismatch{Msg: "length verification failed - expected 1, got 1266"})
 }
 
 func TestUpdateTargetsVersionDivergeSnapshotMetaVersion(t *testing.T) {
@@ -687,7 +687,7 @@ func TestUpdateTargetsVersionDivergeSnapshotMetaVersion(t *testing.T) {
 
 	// New delegate sigfned version != meta version stored in snapshot
 	_, err = trustedSet.UpdateTargets(allRoles[metadata.TARGETS])
-	assert.ErrorIs(t, err, metadata.ErrBadVersionNumber{Msg: "expected targets version 2, got 1"})
+	assert.ErrorIs(t, err, &metadata.ErrBadVersionNumber{Msg: "expected targets version 2, got 1"})
 }
 
 func TestUpdateTargetsExpiredMewTarget(t *testing.T) {
@@ -703,5 +703,5 @@ func TestUpdateTargetsExpiredMewTarget(t *testing.T) {
 	targets, err := modifyTargetsMetadata(modifyTargetExpiry)
 	assert.NoError(t, err)
 	_, err = trustedSet.UpdateTargets(targets)
-	assert.ErrorIs(t, err, metadata.ErrExpiredMetadata{Msg: "new targets is expired"})
+	assert.ErrorIs(t, err, &metadata.ErrExpiredMetadata{Msg: "new targets is expired"})
 }
diff --git a/metadata/updater/updater_top_level_update_test.go b/metadata/updater/updater_top_level_update_test.go
index 598630b..e1dde93 100644
--- a/metadata/updater/updater_top_level_update_test.go
+++ b/metadata/updater/updater_top_level_update_test.go
@@ -329,7 +329,7 @@ func TestTrustedRootExpired(t *testing.T) {
 	assert.NoError(t, err)
 	updater := initUpdater(updaterConfig)
 	err = updater.Refresh()
-	assert.ErrorIs(t, err, metadata.ErrExpiredMetadata{Msg: "final root.json is expired"})
+	assert.ErrorIs(t, err, &metadata.ErrExpiredMetadata{Msg: "final root.json is expired"})
 
 	assertFilesExist(t, []string{metadata.ROOT})
 	version := 2
@@ -368,7 +368,7 @@ func TestTrustedRootUnsigned(t *testing.T) {
 	updaterConfig, err := loadUpdaterConfig()
 	assert.NoError(t, err)
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrUnsignedMetadata{Msg: "Verifying root failed, not enough signatures, got 0, want 1"})
+	assert.ErrorIs(t, err, &metadata.ErrUnsignedMetadata{Msg: "Verifying root failed, not enough signatures, got 0, want 1"})
 
 	assertFilesExist(t, []string{metadata.ROOT})
 	mdRootAfter, err := simulator.Sim.MDRoot.FromFile(rootPath)
@@ -423,7 +423,7 @@ func TestIntermediateRootInclorrectlySigned(t *testing.T) {
 	updaterConfig, err := loadUpdaterConfig()
 	assert.NoError(t, err)
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrUnsignedMetadata{Msg: "Verifying root failed, not enough signatures, got 0, want 1"})
+	assert.ErrorIs(t, err, &metadata.ErrUnsignedMetadata{Msg: "Verifying root failed, not enough signatures, got 0, want 1"})
 
 	assertFilesExist(t, []string{metadata.ROOT})
 	version := 1
@@ -469,7 +469,7 @@ func TestNewRootSameVersion(t *testing.T) {
 	updaterConfig, err := loadUpdaterConfig()
 	assert.NoError(t, err)
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrBadVersionNumber{Msg: "bad version number, expected 2, got 1"})
+	assert.ErrorIs(t, err, &metadata.ErrBadVersionNumber{Msg: "bad version number, expected 2, got 1"})
 
 	// The update failed, latest root version is v1
 	assertFilesExist(t, []string{metadata.ROOT})
@@ -488,7 +488,7 @@ func TestNewRootNonconsecutiveVersion(t *testing.T) {
 	updaterConfig, err := loadUpdaterConfig()
 	assert.NoError(t, err)
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrBadVersionNumber{Msg: "bad version number, expected 2, got 3"})
+	assert.ErrorIs(t, err, &metadata.ErrBadVersionNumber{Msg: "bad version number, expected 2, got 3"})
 
 	// The update failed, latest root version is v1
 	assertFilesExist(t, []string{metadata.ROOT})
@@ -509,7 +509,7 @@ func TestFinalRootExpired(t *testing.T) {
 	updaterConfig, err := loadUpdaterConfig()
 	assert.NoError(t, err)
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrExpiredMetadata{Msg: "final root.json is expired"})
+	assert.ErrorIs(t, err, &metadata.ErrExpiredMetadata{Msg: "final root.json is expired"})
 
 	// The update failed but final root is persisted on the file system
 	assertFilesExist(t, []string{metadata.ROOT})
@@ -527,7 +527,7 @@ func TestNewTimestampUnsigned(t *testing.T) {
 	updaterConfig, err := loadUpdaterConfig()
 	assert.NoError(t, err)
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrUnsignedMetadata{Msg: "Verifying timestamp failed, not enough signatures, got 0, want 1"})
+	assert.ErrorIs(t, err, &metadata.ErrUnsignedMetadata{Msg: "Verifying timestamp failed, not enough signatures, got 0, want 1"})
 
 	assertFilesExist(t, []string{metadata.ROOT})
 }
@@ -563,7 +563,7 @@ func TestExpiredTimestampVersionRollback(t *testing.T) {
 	// local timestamp has expired
 	moveInTime := time.Now().Add(time.Hour * 18 * 24)
 	_, err = runRefresh(updaterConfig, moveInTime)
-	assert.ErrorIs(t, err, metadata.ErrBadVersionNumber{Msg: "new timestamp version 1 must be >= 2"})
+	assert.ErrorIs(t, err, &metadata.ErrBadVersionNumber{Msg: "new timestamp version 1 must be >= 2"})
 	assertVersionEquals(t, metadata.TIMESTAMP, 2)
 }
 
@@ -580,7 +580,7 @@ func TestNewTimestampVersionRollback(t *testing.T) {
 
 	simulator.Sim.MDTimestamp.Signed.Version = 1
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrBadVersionNumber{Msg: "new timestamp version 1 must be >= 2"})
+	assert.ErrorIs(t, err, &metadata.ErrBadVersionNumber{Msg: "new timestamp version 1 must be >= 2"})
 	assertVersionEquals(t, metadata.TIMESTAMP, 2)
 }
 
@@ -600,7 +600,7 @@ func TestNewTimestampSnapshotRollback(t *testing.T) {
 	simulator.Sim.MDTimestamp.Signed.Meta["snapshot.json"].Version = 1
 	simulator.Sim.MDTimestamp.Signed.Version += 1 // timestamp v3
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrBadVersionNumber{Msg: "new snapshot version 1 must be >= 2"})
+	assert.ErrorIs(t, err, &metadata.ErrBadVersionNumber{Msg: "new snapshot version 1 must be >= 2"})
 	assertVersionEquals(t, metadata.TIMESTAMP, 2)
 }
 
@@ -614,7 +614,7 @@ func TestNewTimestampExpired(t *testing.T) {
 	updaterConfig, err := loadUpdaterConfig()
 	assert.NoError(t, err)
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrExpiredMetadata{Msg: "timestamp.json is expired"})
+	assert.ErrorIs(t, err, &metadata.ErrExpiredMetadata{Msg: "timestamp.json is expired"})
 	assertFilesExist(t, []string{metadata.ROOT})
 }
 
@@ -675,7 +675,7 @@ func TestNewSnapshotHashMismatch(t *testing.T) {
 
 	// Hash mismatch error
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrLengthOrHashMismatch{Msg: "hash verification failed - mismatch for algorithm sha256"})
+	assert.ErrorIs(t, err, &metadata.ErrLengthOrHashMismatch{Msg: "hash verification failed - mismatch for algorithm sha256"})
 	assertVersionEquals(t, metadata.TIMESTAMP, 3)
 	assertVersionEquals(t, metadata.SNAPSHOT, 1)
 }
@@ -689,7 +689,7 @@ func TestNewSnapshotUnsigned(t *testing.T) {
 	updaterConfig, err := loadUpdaterConfig()
 	assert.NoError(t, err)
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrUnsignedMetadata{Msg: "Verifying snapshot failed, not enough signatures, got 0, want 1"})
+	assert.ErrorIs(t, err, &metadata.ErrUnsignedMetadata{Msg: "Verifying snapshot failed, not enough signatures, got 0, want 1"})
 
 	assertFilesExist(t, []string{metadata.ROOT, metadata.TIMESTAMP})
 }
@@ -706,7 +706,7 @@ func TestNewSnapshotVersionMismatch(t *testing.T) {
 	updaterConfig, err := loadUpdaterConfig()
 	assert.NoError(t, err)
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrBadVersionNumber{Msg: "expected 1, got 2"})
+	assert.ErrorIs(t, err, &metadata.ErrBadVersionNumber{Msg: "expected 1, got 2"})
 
 	assertFilesExist(t, []string{metadata.ROOT, metadata.TIMESTAMP})
 }
@@ -726,7 +726,7 @@ func TestNewSnapshotVersionRollback(t *testing.T) {
 	simulator.Sim.MDSnapshot.Signed.Version = 1
 	simulator.Sim.UpdateTimestamp()
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrBadVersionNumber{Msg: "new snapshot version 1 must be >= 2"})
+	assert.ErrorIs(t, err, &metadata.ErrBadVersionNumber{Msg: "new snapshot version 1 must be >= 2"})
 
 	assertVersionEquals(t, metadata.SNAPSHOT, 2)
 }
@@ -782,7 +782,7 @@ func TestNewSnapshotExpired(t *testing.T) {
 	updaterConfig, err := loadUpdaterConfig()
 	assert.NoError(t, err)
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrExpiredMetadata{Msg: "snapshot.json is expired"})
+	assert.ErrorIs(t, err, &metadata.ErrExpiredMetadata{Msg: "snapshot.json is expired"})
 
 	assertFilesExist(t, []string{metadata.ROOT})
 }
@@ -807,7 +807,7 @@ func TestNewTargetsHashMismatch(t *testing.T) {
 	simulator.Sim.UpdateTimestamp()
 
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrLengthOrHashMismatch{Msg: "hash verification failed - mismatch for algorithm sha256"})
+	assert.ErrorIs(t, err, &metadata.ErrLengthOrHashMismatch{Msg: "hash verification failed - mismatch for algorithm sha256"})
 
 	assertVersionEquals(t, metadata.SNAPSHOT, 3)
 	assertVersionEquals(t, metadata.TARGETS, 1)
@@ -823,7 +823,7 @@ func TestNewTargetsUnsigned(t *testing.T) {
 	updaterConfig, err := loadUpdaterConfig()
 	assert.NoError(t, err)
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrUnsignedMetadata{Msg: "Verifying targets failed, not enough signatures, got 0, want 1"})
+	assert.ErrorIs(t, err, &metadata.ErrUnsignedMetadata{Msg: "Verifying targets failed, not enough signatures, got 0, want 1"})
 
 	assertFilesExist(t, []string{metadata.ROOT, metadata.TIMESTAMP, metadata.SNAPSHOT})
 }
@@ -839,7 +839,7 @@ func TestNewTargetsVersionMismatch(t *testing.T) {
 	updaterConfig, err := loadUpdaterConfig()
 	assert.NoError(t, err)
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrBadVersionNumber{Msg: "expected targets version 1, got 2"})
+	assert.ErrorIs(t, err, &metadata.ErrBadVersionNumber{Msg: "expected targets version 1, got 2"})
 
 	assertFilesExist(t, []string{metadata.ROOT, metadata.TIMESTAMP, metadata.SNAPSHOT})
 }
@@ -855,7 +855,7 @@ func TestNewTargetsExpired(t *testing.T) {
 	updaterConfig, err := loadUpdaterConfig()
 	assert.NoError(t, err)
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrExpiredMetadata{Msg: "new targets is expired"})
+	assert.ErrorIs(t, err, &metadata.ErrExpiredMetadata{Msg: "new targets is expired"})
 
 	assertFilesExist(t, []string{metadata.ROOT, metadata.TIMESTAMP, metadata.SNAPSHOT})
 }
@@ -957,7 +957,7 @@ func TestSnapshotRollbackWithLocalSnapshotHashMismatch(t *testing.T) {
 	// Should fail as a new version of snapshot will be fetched which lowers
 	// the snapshot meta "targets.json" version by 1 and throws an error.
 	_, err = runRefresh(updaterConfig, time.Now())
-	assert.ErrorIs(t, err, metadata.ErrBadVersionNumber{Msg: "expected targets.json version 1, got 2"})
+	assert.ErrorIs(t, err, &metadata.ErrBadVersionNumber{Msg: "expected targets.json version 1, got 2"})
 }
 
 func TestExpiredMetadata(t *testing.T) {
@@ -1027,27 +1027,27 @@ func TestMaxMetadataLengths(t *testing.T) {
 	updater := initUpdater(updaterConfig)
 	updater.cfg.RootMaxLength = 100
 	err = updater.Refresh()
-	assert.ErrorIs(t, err, metadata.ErrDownloadLengthMismatch{Msg: "Downloaded 1567 bytes exceeding the maximum allowed length of 100"})
+	assert.ErrorIs(t, err, &metadata.ErrDownloadLengthMismatch{Msg: "Downloaded 1567 bytes exceeding the maximum allowed length of 100"})
 
 	updater = initUpdater(updaterConfig)
 	updater.cfg.TimestampMaxLength = 100
 	err = updater.Refresh()
-	assert.ErrorIs(t, err, metadata.ErrDownloadLengthMismatch{Msg: "Downloaded 1567 bytes exceeding the maximum allowed length of 100"})
+	assert.ErrorIs(t, err, &metadata.ErrDownloadLengthMismatch{Msg: "Downloaded 1567 bytes exceeding the maximum allowed length of 100"})
 
 	updater = initUpdater(updaterConfig)
 	updater.cfg.SnapshotMaxLength = 100
 	err = updater.Refresh()
-	assert.ErrorIs(t, err, metadata.ErrDownloadLengthMismatch{Msg: "Downloaded 1567 bytes exceeding the maximum allowed length of 100"})
+	assert.ErrorIs(t, err, &metadata.ErrDownloadLengthMismatch{Msg: "Downloaded 1567 bytes exceeding the maximum allowed length of 100"})
 
 	updater = initUpdater(updaterConfig)
 	updater.cfg.TargetsMaxLength = 100
 	err = updater.Refresh()
-	assert.ErrorIs(t, err, metadata.ErrDownloadLengthMismatch{Msg: "Downloaded 1567 bytes exceeding the maximum allowed length of 100"})
+	assert.ErrorIs(t, err, &metadata.ErrDownloadLengthMismatch{Msg: "Downloaded 1567 bytes exceeding the maximum allowed length of 100"})
 
 	// All good with normal length limits
 	updater = initUpdater(updaterConfig)
 	err = updater.Refresh()
-	assert.ErrorIs(t, err, metadata.ErrDownloadLengthMismatch{Msg: "Downloaded 1567 bytes exceeding the maximum allowed length of 100"})
+	assert.ErrorIs(t, err, &metadata.ErrDownloadLengthMismatch{Msg: "Downloaded 1567 bytes exceeding the maximum allowed length of 100"})
 }
 
 func TestTimestampEqVersionsCheck(t *testing.T) {
diff --git a/testutils/simulator/repository_simulator.go b/testutils/simulator/repository_simulator.go
index 926b874..76654e5 100644
--- a/testutils/simulator/repository_simulator.go
+++ b/testutils/simulator/repository_simulator.go
@@ -308,7 +308,7 @@ func (rs *RepositorySimulator) DownloadFile(urlPath string, maxLength int64, tim
 		return data, err
 	}
 	if len(data) > int(maxLength) {
-		err = metadata.ErrDownloadLengthMismatch{
+		err = &metadata.ErrDownloadLengthMismatch{
 			Msg: fmt.Sprintf("Downloaded %d bytes exceeding the maximum allowed length of %d", len(data), maxLength),
 		}
 	}
@@ -418,7 +418,7 @@ func (rs *RepositorySimulator) FetchMetadata(role string, version *int) ([]byte,
 		// Return a version previously serialized in PublishRoot()
 		if version == nil || *version > len(rs.SignedRoots) && *version > 0 {
 			log.Printf("unknown root version %d", *version)
-			return []byte{}, metadata.ErrDownloadHTTP{StatusCode: 404}
+			return []byte{}, &metadata.ErrDownloadHTTP{StatusCode: 404}
 		}
 		log.Printf("fetched root version %d", version)
 		return rs.SignedRoots[*version-1], nil
@@ -435,7 +435,7 @@ func (rs *RepositorySimulator) FetchMetadata(role string, version *int) ([]byte,
 		md, ok := rs.MDDelegates[role]
 		if !ok {
 			log.Printf("unknown role %s", role)
-			return []byte{}, metadata.ErrDownloadHTTP{StatusCode: 404}
+			return []byte{}, &metadata.ErrDownloadHTTP{StatusCode: 404}
 		}
 		return signMetadata(role, &md, rs)
 	}