Repository: ratify-project/ratify
Pull request #1730 (2024-08-20 08:57:04)

chore: Refactor error messages for Notation signature verification
# Description

## What this PR does / why we need it:
This PR focuses on the notation signature validation scenario, improving the clarity of error messages and providing more intuitive remediation steps for users.

For errors that are self-explanatory, I have not included remediation steps.

## Which issue(s) this PR fixes *(optional, using `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when the PR gets merged)*:
It will fix some cases of the issue: https://github.com/ratify-project/ratify/issues/1321

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Helm Chart Change (any edit/addition/update that is necessary for changes merged to the `main` branch)
- [ ] This change requires a documentation update

# How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Please also list any relevant details for your test configuration

- [ ] Test A
- [ ] Test B

# Checklist:

- [ ] Does the affected code have corresponding tests?
- [ ] Are the changes documented, not just with inline documentation, but also with conceptual documentation such as an overview of a new feature, or task-based documentation like a tutorial? Consider if this change should be announced on your project blog.
- [ ] Does this introduce breaking changes that would require an announcement or bumping the major version?
- [ ] Do all new files have appropriate license header?

# Post Merge Requirements
- [ ] MAINTAINERS: manually trigger the "Publish Package" workflow after merging any PR that indicates `Helm Chart Change`


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project) Report
Attention: Patch coverage is `51.16279%` with `21 lines` in your changes missing coverage. Please review.

| [Files](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project) | Patch % | Lines |
|---|---|---|
| [pkg/verifier/factory/factory.go](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&filepath=pkg%2Fverifier%2Ffactory%2Ffactory.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-cGtnL3ZlcmlmaWVyL2ZhY3RvcnkvZmFjdG9yeS5nbw==) | 0.00% | [8 Missing :warning: ](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project) |
| [pkg/referrerstore/oras/oras.go](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&filepath=pkg%2Freferrerstore%2Foras%2Foras.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-cGtnL3JlZmVycmVyc3RvcmUvb3Jhcy9vcmFzLmdv) | 12.50% | [7 Missing :warning: ](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project) |
| [pkg/verifier/notation/notation.go](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&filepath=pkg%2Fverifier%2Fnotation%2Fnotation.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-cGtnL3ZlcmlmaWVyL25vdGF0aW9uL25vdGF0aW9uLmdv) | 76.92% | [3 Missing :warning: ](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project) |
| [pkg/executor/core/executor.go](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&filepath=pkg%2Fexecutor%2Fcore%2Fexecutor.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-cGtnL2V4ZWN1dG9yL2NvcmUvZXhlY3V0b3IuZ28=) | 60.00% | [2 Missing :warning: ](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project) |
| [pkg/verifier/notation/truststore.go](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&filepath=pkg%2Fverifier%2Fnotation%2Ftruststore.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-cGtnL3ZlcmlmaWVyL25vdGF0aW9uL3RydXN0c3RvcmUuZ28=) | 0.00% | [1 Missing :warning: ](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project) |

| [Files](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project) | Coverage Δ | |
|---|---|---|
| [...controllers/clusterresource/verifier\_controller.go](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&filepath=pkg%2Fcontrollers%2Fclusterresource%2Fverifier_controller.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-cGtnL2NvbnRyb2xsZXJzL2NsdXN0ZXJyZXNvdXJjZS92ZXJpZmllcl9jb250cm9sbGVyLmdv) | `80.00% <100.00%> (ø)` | |
| [...ntrollers/namespaceresource/verifier\_controller.go](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&filepath=pkg%2Fcontrollers%2Fnamespaceresource%2Fverifier_controller.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-cGtnL2NvbnRyb2xsZXJzL25hbWVzcGFjZXJlc291cmNlL3ZlcmlmaWVyX2NvbnRyb2xsZXIuZ28=) | `80.00% <100.00%> (ø)` | |
| [pkg/controllers/utils/verifier.go](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&filepath=pkg%2Fcontrollers%2Futils%2Fverifier.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-cGtnL2NvbnRyb2xsZXJzL3V0aWxzL3ZlcmlmaWVyLmdv) | `100.00% <100.00%> (ø)` | |
| [pkg/verifier/notation/certstoresbytype.go](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&filepath=pkg%2Fverifier%2Fnotation%2Fcertstoresbytype.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-cGtnL3ZlcmlmaWVyL25vdGF0aW9uL2NlcnRzdG9yZXNieXR5cGUuZ28=) | `92.59% <100.00%> (ø)` | |
| [pkg/verifier/notation/truststore.go](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&filepath=pkg%2Fverifier%2Fnotation%2Ftruststore.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-cGtnL3ZlcmlmaWVyL25vdGF0aW9uL3RydXN0c3RvcmUuZ28=) | `84.00% <0.00%> (ø)` | |
| [pkg/executor/core/executor.go](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&filepath=pkg%2Fexecutor%2Fcore%2Fexecutor.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-cGtnL2V4ZWN1dG9yL2NvcmUvZXhlY3V0b3IuZ28=) | `88.46% <60.00%> (-0.70%)` | :arrow_down: |
| [pkg/verifier/notation/notation.go](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&filepath=pkg%2Fverifier%2Fnotation%2Fnotation.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-cGtnL3ZlcmlmaWVyL25vdGF0aW9uL25vdGF0aW9uLmdv) | `87.36% <76.92%> (-0.76%)` | :arrow_down: |
| [pkg/referrerstore/oras/oras.go](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&filepath=pkg%2Freferrerstore%2Foras%2Foras.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-cGtnL3JlZmVycmVyc3RvcmUvb3Jhcy9vcmFzLmdv) | `67.78% <12.50%> (ø)` | |
| [pkg/verifier/factory/factory.go](https://app.codecov.io/gh/ratify-project/ratify/pull/1730?src=pr&el=tree&filepath=pkg%2Fverifier%2Ffactory%2Ffactory.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-cGtnL3ZlcmlmaWVyL2ZhY3RvcnkvZmFjdG9yeS5nbw==) | `65.51% <0.00%> (ø)` | |

... and [3 files with indirect coverage changes](https://app.codecov.io/gh/ratify-project/ratify/pull/1730/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project)

binbin-li: @yizha1 thanks a lot for your feedback, could you take another look? I've addressed all comments.

Patch:
diff --git a/pkg/controllers/clusterresource/verifier_controller.go b/pkg/controllers/clusterresource/verifier_controller.go
index 2b72459..c8c8cd8 100644
--- a/pkg/controllers/clusterresource/verifier_controller.go
+++ b/pkg/controllers/clusterresource/verifier_controller.go
@@ -17,6 +17,7 @@ package clusterresource
 
 import (
 	"context"
+	"fmt"
 
 	configv1beta1 "github.com/ratify-project/ratify/api/v1beta1"
 	re "github.com/ratify-project/ratify/errors"
@@ -82,12 +83,13 @@ func (r *VerifierReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
 	return ctrl.Result{}, nil
 }
 
-// creates a verifier reference from CRD spec and add store to map
+// creates a verifier reference from CR spec and add verifier to map
 func verifierAddOrReplace(spec configv1beta1.VerifierSpec, objectName string) error {
 	verifierConfig, err := cutils.SpecToVerifierConfig(spec.Parameters.Raw, objectName, spec.Name, spec.ArtifactTypes, spec.Source)
 	if err != nil {
-		logrus.Error(err)
-		return err
+		errMsg := fmt.Sprintf("Unable to apply cluster-wide resource %s of Verifier kind", objectName)
+		logrus.Error(err, errMsg)
+		return re.ErrorCodeConfigInvalid.WithDetail(errMsg).WithError(err)
 	}
 
 	return cutils.UpsertVerifier(spec.Version, spec.Address, constants.EmptyNamespace, objectName, verifierConfig)
diff --git a/pkg/controllers/namespaceresource/verifier_controller.go b/pkg/controllers/namespaceresource/verifier_controller.go
index e78bd8d..4b19b61 100644
--- a/pkg/controllers/namespaceresource/verifier_controller.go
+++ b/pkg/controllers/namespaceresource/verifier_controller.go
@@ -17,6 +17,7 @@ package namespaceresource
 
 import (
 	"context"
+	"fmt"
 
 	configv1beta1 "github.com/ratify-project/ratify/api/v1beta1"
 	"github.com/ratify-project/ratify/internal/constants"
@@ -85,8 +86,9 @@ func (r *VerifierReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
 func verifierAddOrReplace(spec configv1beta1.NamespacedVerifierSpec, objectName string, namespace string) error {
 	verifierConfig, err := cutils.SpecToVerifierConfig(spec.Parameters.Raw, objectName, spec.Name, spec.ArtifactTypes, spec.Source)
 	if err != nil {
-		logrus.Error(err)
-		return err
+		errMsg := fmt.Sprintf("Unable to apply the resource %s of NamespacedVerifier kind in the namespace %s", objectName, namespace)
+		logrus.Error(err, errMsg)
+		return re.ErrorCodeConfigInvalid.WithDetail(errMsg).WithError(err)
 	}
 
 	return cutils.UpsertVerifier(spec.Version, spec.Address, namespace, objectName, verifierConfig)
diff --git a/pkg/controllers/utils/verifier.go b/pkg/controllers/utils/verifier.go
index 0b25579..e65a059 100644
--- a/pkg/controllers/utils/verifier.go
+++ b/pkg/controllers/utils/verifier.go
@@ -15,8 +15,10 @@ package utils
 
 import (
 	"encoding/json"
+	"fmt"
 
 	configv1beta1 "github.com/ratify-project/ratify/api/v1beta1"
+	re "github.com/ratify-project/ratify/errors"
 	vc "github.com/ratify-project/ratify/pkg/verifier/config"
 	vf "github.com/ratify-project/ratify/pkg/verifier/factory"
 	"github.com/ratify-project/ratify/pkg/verifier/types"
@@ -56,8 +58,9 @@ func SpecToVerifierConfig(raw []byte, verifierName, verifierType, artifactTypes
 
 	if string(raw) != "" {
 		if err := json.Unmarshal(raw, &verifierConfig); err != nil {
-			logrus.Error(err, "unable to decode verifier parameters", "Parameters.Raw", raw)
-			return vc.VerifierConfig{}, err
+			errMsg := fmt.Sprintf("Unable to recognize the parameters of the Verifier resource %s", string(raw))
+			logrus.Error(err, errMsg)
+			return vc.VerifierConfig{}, re.ErrorCodeConfigInvalid.WithError(err).WithDetail(errMsg).WithRemediation("Please update the Verifier parameters and try again. Refer to the Verifier configuration guide: https://ratify.dev/docs/reference/custom%20resources/verifiers")
 		}
 	}
 	verifierConfig[types.Name] = verifierName
diff --git a/pkg/executor/core/executor.go b/pkg/executor/core/executor.go
index e5d8ec2..b364bee 100644
--- a/pkg/executor/core/executor.go
+++ b/pkg/executor/core/executor.go
@@ -61,7 +61,7 @@ type Executor struct {
 // VerifySubject verifies the subject and returns results.
 func (executor Executor) VerifySubject(ctx context.Context, verifyParameters e.VerifyParameters) (types.VerifyResult, error) {
 	if executor.PolicyEnforcer == nil {
-		return types.VerifyResult{}, errors.ErrorCodePolicyProviderNotFound.WithComponentType(errors.Executor)
+		return types.VerifyResult{}, errors.ErrorCodePolicyProviderNotFound.WithDetail("Policy configuration not found")
 	}
 	result, err := executor.verifySubjectInternal(ctx, verifyParameters)
 	if err != nil {
@@ -83,7 +83,7 @@ func (executor Executor) verifySubjectInternal(ctx context.Context, verifyParame
 	}
 	if executor.PolicyEnforcer.GetPolicyType(ctx) == pt.ConfigPolicy {
 		if len(verifierReports) == 0 {
-			return types.VerifyResult{}, errors.ErrorCodeNoVerifierReport.WithComponentType(errors.Executor).WithDescription()
+			return types.VerifyResult{}, errors.ErrorCodeNoVerifierReport.WithDetail(fmt.Sprintf("No verification results for the artifact %s. Ensure verifiers are properly configured and that artifact metadata is attached", verifyParameters.Subject))
 		}
 	}
 	// If it requires embedded Rego Policy Engine make the decision, execute
@@ -176,7 +176,7 @@ func (executor Executor) verifyReferenceForJSONPolicy(ctx context.Context, subje
 			verifierStartTime := time.Now()
 			verifyResult, err := verifier.Verify(ctx, subjectRef, referenceDesc, referrerStore)
 			if err != nil {
-				verifierErr := errors.ErrorCodeVerifyReferenceFailure.NewError(errors.Verifier, verifier.Name(), errors.EmptyLink, err, nil, errors.HideStackTrace)
+				verifierErr := errors.ErrorCodeVerifyReferenceFailure.WithError(err)
 				verifyResult = vr.NewVerifierResult("", verifier.Name(), verifier.Type(), "", false, &verifierErr, nil)
 			}
 
@@ -224,7 +224,7 @@ func (executor Executor) verifyReferenceForRegoPolicy(ctx context.Context, subje
 			verifierStartTime := time.Now()
 			verifierResult, err := verifier.Verify(errCtx, subjectRef, referenceDesc, referrerStore)
 			if err != nil {
-				verifierErr := errors.ErrorCodeVerifyReferenceFailure.NewError(errors.Verifier, verifier.Name(), errors.EmptyLink, err, nil, errors.HideStackTrace)
+				verifierErr := errors.ErrorCodeVerifyReferenceFailure.WithError(err)
 				verifierReport = vt.CreateVerifierResult(verifier.Name(), verifier.Type(), "", false, &verifierErr)
 			} else {
 				verifierReport = vt.NewVerifierResult(verifierResult)
@@ -288,7 +288,7 @@ func (executor Executor) addNestedReports(ctx context.Context, referenceDes ocis
 	for _, report := range reports.VerifierReports {
 		nestedReport, err := types.NewNestedVerifierReport(report)
 		if err != nil {
-			return errors.ErrorCodeExecutorFailure.WithError(err).WithComponentType(errors.Executor)
+			return errors.ErrorCodeExecutorFailure.WithError(err)
 		}
 		nestedReports = append(nestedReports, nestedReport)
 	}
diff --git a/pkg/keymanagementprovider/keymanagementprovider.go b/pkg/keymanagementprovider/keymanagementprovider.go
index bf77c2c..584f508 100644
--- a/pkg/keymanagementprovider/keymanagementprovider.go
+++ b/pkg/keymanagementprovider/keymanagementprovider.go
@@ -136,7 +136,7 @@ func setCertificatesInMap(resource string, certs map[KMPMapKey][]*x509.Certifica
 // GetCertificatesFromMap gets the certificates from the map and returns an empty map of certificate arrays if not found or an error happened.
 func GetCertificatesFromMap(ctx context.Context, resource string) (map[KMPMapKey][]*x509.Certificate, error) {
 	if !hasAccessToProvider(ctx, resource) {
-		return map[KMPMapKey][]*x509.Certificate{}, errors.ErrorCodeForbidden.WithDetail(fmt.Sprintf("namespace: [%s] does not have access to key management provider: %s", ctxUtils.GetNamespace(ctx), resource)).WithRemediation(fmt.Sprintf("Ensure the key management provider: %s is created under namespace: [%s] or as a cluster-wide resource.", resource, ctxUtils.GetNamespace(ctx)))
+		return map[KMPMapKey][]*x509.Certificate{}, errors.ErrorCodeForbidden.WithDetail(fmt.Sprintf("Resources in namespace [%s] do not have access to key management provider [%s]", ctxUtils.GetNamespace(ctx), resource)).WithRemediation(fmt.Sprintf("Make sure the key management provider: %s is created in the namespace: [%s] or as a cluster-wide resource.", resource, ctxUtils.GetNamespace(ctx)))
 	}
 	if err, ok := certificateErrMap.Load(resource); ok && err != nil {
 		return map[KMPMapKey][]*x509.Certificate{}, err.(error)
@@ -144,7 +144,7 @@ func GetCertificatesFromMap(ctx context.Context, resource string) (map[KMPMapKey
 	if certs, ok := certificatesMap.Load(resource); ok {
 		return certs.(map[KMPMapKey][]*x509.Certificate), nil
 	}
-	return map[KMPMapKey][]*x509.Certificate{}, errors.ErrorCodeNotFound.WithDetail(fmt.Sprintf("failed to access non-existent key management provider: %s", resource))
+	return map[KMPMapKey][]*x509.Certificate{}, errors.ErrorCodeNotFound.WithDetail(fmt.Sprintf("The key management provider [%s] does not exist", resource)).WithRemediation(fmt.Sprintf("Make sure the key management provider: %s is created in the namespace: [%s] or as a cluster-wide resource.", resource, ctxUtils.GetNamespace(ctx)))
 }
 
 // DeleteResourceFromMap deletes the certificates, keys and errors from the map
@@ -186,7 +186,7 @@ func GetKeysFromMap(ctx context.Context, resource string) (map[KMPMapKey]PublicK
 	// A cluster-wide operation can access cluster-wide provider
 	// A namespaced operation can only fetch the provider in the same namespace or cluster-wide provider.
 	if !hasAccessToProvider(ctx, resource) {
-		return map[KMPMapKey]PublicKey{}, fmt.Errorf("namespace: [%s] does not have access to key management provider: %s", ctxUtils.GetNamespace(ctx), resource)
+		return map[KMPMapKey]PublicKey{}, errors.ErrorCodeForbidden.WithDetail(fmt.Sprintf("The resources in namespace [%s] do not have access to key management provider [%s]", ctxUtils.GetNamespace(ctx), resource)).WithRemediation(fmt.Sprintf("Make sure the key management provider [%s] is created in the namespace [%s] or as a cluster-wide resource.", resource, ctxUtils.GetNamespace(ctx)))
 	}
 	if err, ok := keyErrMap.Load(resource); ok && err != nil {
 		return map[KMPMapKey]PublicKey{}, err.(error)
@@ -194,7 +194,7 @@ func GetKeysFromMap(ctx context.Context, resource string) (map[KMPMapKey]PublicK
 	if keys, ok := keyMap.Load(resource); ok {
 		return keys.(map[KMPMapKey]PublicKey), nil
 	}
-	return map[KMPMapKey]PublicKey{}, fmt.Errorf("failed to access non-existent key management provider: %s", resource)
+	return map[KMPMapKey]PublicKey{}, errors.ErrorCodeNotFound.WithDetail(fmt.Sprintf("The key management provider [%s] does not exist", resource)).WithRemediation(fmt.Sprintf("Make sure the key management provider: %s is created in the namespace: [%s] or as a cluster-wide resource.", resource, ctxUtils.GetNamespace(ctx)))
 }
 
 // SetCertificateError sets the error while fetching certificates from key management provider.
diff --git a/pkg/referrerstore/oras/oras.go b/pkg/referrerstore/oras/oras.go
index 0a8f146..a8462d2 100644
--- a/pkg/referrerstore/oras/oras.go
+++ b/pkg/referrerstore/oras/oras.go
@@ -313,7 +313,7 @@ func (store *orasStore) GetBlobContent(ctx context.Context, subjectReference com
 func (store *orasStore) GetReferenceManifest(ctx context.Context, subjectReference common.Reference, referenceDesc ocispecs.ReferenceDescriptor) (ocispecs.ReferenceManifest, error) {
 	repository, err := store.createRepository(ctx, store, subjectReference)
 	if err != nil {
-		return ocispecs.ReferenceManifest{}, re.ErrorCodeCreateRepositoryFailure.NewError(re.ReferrerStore, storeName, re.EmptyLink, err, nil, re.HideStackTrace)
+		return ocispecs.ReferenceManifest{}, re.ErrorCodeRepositoryOperationFailure.WithDetail("Failed to connect to the remote registry").WithError(err)
 	}
 	var manifestBytes []byte
 	// check if manifest exists in local ORAS cache
@@ -336,12 +336,12 @@ func (store *orasStore) GetReferenceManifest(ctx context.Context, subjectReferen
 		manifestReader, err := repository.Fetch(ctx, referenceDesc.Descriptor)
 		if err != nil {
 			evictOnError(ctx, err, subjectReference.Original)
-			return ocispecs.ReferenceManifest{}, re.ErrorCodeRepositoryOperationFailure.NewError(re.ReferrerStore, storeName, re.EmptyLink, err, nil, re.HideStackTrace)
+			return ocispecs.ReferenceManifest{}, re.ErrorCodeRepositoryOperationFailure.WithDetail("Failed to fetch the artifact metadata from the registry").WithError(err)
 		}
 
 		manifestBytes, err = io.ReadAll(manifestReader)
 		if err != nil {
-			return ocispecs.ReferenceManifest{}, re.ErrorCodeManifestInvalid.WithError(err).WithPluginName(storeName).WithComponentType(re.ReferrerStore)
+			return ocispecs.ReferenceManifest{}, re.ErrorCodeManifestInvalid.WithDetail("Failed to parse the artifact metadata").WithError(err)
 		}
 
 		// push fetched manifest to local ORAS cache
@@ -360,15 +360,15 @@ func (store *orasStore) GetReferenceManifest(ctx context.Context, subjectReferen
 	if referenceDesc.Descriptor.MediaType == oci.MediaTypeImageManifest {
 		var imageManifest oci.Manifest
 		if err := json.Unmarshal(manifestBytes, &imageManifest); err != nil {
-			return ocispecs.ReferenceManifest{}, re.ErrorCodeDataDecodingFailure.WithError(err).WithComponentType(re.ReferrerStore)
+			return ocispecs.ReferenceManifest{}, re.ErrorCodeDataDecodingFailure.WithDetail("Failed to parse artifact metadata of mediatype `application/vnd.oci.image.manifest.v1+json`").WithError(err).WithRemediation("Please check if the artifact metadata was created correctly.")
 		}
 		referenceManifest = commonutils.OciManifestToReferenceManifest(imageManifest)
 	} else if referenceDesc.Descriptor.MediaType == ocispecs.MediaTypeArtifactManifest {
 		if err := json.Unmarshal(manifestBytes, &referenceManifest); err != nil {
-			return ocispecs.ReferenceManifest{}, re.ErrorCodeDataDecodingFailure.WithError(err).WithComponentType(re.ReferrerStore)
+			return ocispecs.ReferenceManifest{}, re.ErrorCodeDataDecodingFailure.WithDetail("Failed to parse artifact metadata of mediatype `application/vnd.oci.artifact.manifest.v1+json`").WithError(err).WithRemediation("Please check if the artifact metadata was created correctly.")
 		}
 	} else {
-		return ocispecs.ReferenceManifest{}, fmt.Errorf("unsupported manifest media type: %s", referenceDesc.Descriptor.MediaType)
+		return ocispecs.ReferenceManifest{}, re.ErrorCodeGetReferenceManifestFailure.WithDetail(fmt.Sprintf("Unsupported artifact metadata of media type %s", referenceDesc.Descriptor.MediaType)).WithRemediation("Please check if the artifact metadata was created correctly.")
 	}
 
 	return referenceManifest, nil
@@ -377,13 +377,13 @@ func (store *orasStore) GetReferenceManifest(ctx context.Context, subjectReferen
 func (store *orasStore) GetSubjectDescriptor(ctx context.Context, subjectReference common.Reference) (*ocispecs.SubjectDescriptor, error) {
 	repository, err := store.createRepository(ctx, store, subjectReference)
 	if err != nil {
-		return nil, re.ErrorCodeCreateRepositoryFailure.WithError(err).WithComponentType(re.ReferrerStore).WithPluginName(storeName)
+		return nil, re.ErrorCodeRepositoryOperationFailure.WithDetail("Failed to connect to remote registry").WithError(err)
 	}
 
 	desc, err := repository.Resolve(ctx, subjectReference.Original)
 	if err != nil {
 		evictOnError(ctx, err, subjectReference.Original)
-		return nil, re.ErrorCodeRepositoryOperationFailure.WithError(err).WithPluginName(storeName)
+		return nil, re.ErrorCodeRepositoryOperationFailure.WithDetail(fmt.Sprintf("Unable to resolve the reference: %s", subjectReference.Original)).WithError(err)
 	}
 
 	return &ocispecs.SubjectDescriptor{Descriptor: desc}, nil
diff --git a/pkg/verifier/factory/factory.go b/pkg/verifier/factory/factory.go
index a23bdcf..fdc6e57 100644
--- a/pkg/verifier/factory/factory.go
+++ b/pkg/verifier/factory/factory.go
@@ -53,12 +53,12 @@ func Register(name string, factory VerifierFactory) {
 // namespace is only applicable in K8s environment, namespace is appended to the certstore of the truststore so it is uniquely identifiable in a cluster env
 // the first element of pluginBinDir will be used as the plugin directory
 func CreateVerifierFromConfig(verifierConfig config.VerifierConfig, configVersion string, pluginBinDir []string, namespace string) (verifier.ReferenceVerifier, error) {
-	// in cli mode both `type` and `name`` are read from config, if `type` is not specified, `name` is used as `type`
+	// in cli mode both `type` and `name` are read from config, if `type` is not specified, `name` is used as `type`
 	var verifierTypeStr string
 	if value, ok := verifierConfig[types.Name]; ok {
 		verifierTypeStr = value.(string)
 	} else {
-		return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("failed to find verifier name in the verifier config with key %s", "name"))
+		return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("The name field is required in the Verifier configuration: %+v", verifierConfig))
 	}
 
 	if value, ok := verifierConfig[types.Type]; ok {
@@ -66,7 +66,7 @@ func CreateVerifierFromConfig(verifierConfig config.VerifierConfig, configVersio
 	}
 
 	if strings.ContainsRune(verifierTypeStr, os.PathSeparator) {
-		return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("invalid plugin name for a verifier: %s", verifierTypeStr))
+		return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Invalid name [%s] in the Verifier configuration, [%v] is disallowed", verifierTypeStr, os.PathSeparator))
 	}
 
 	// if source is specified, download the plugin
@@ -74,13 +74,13 @@ func CreateVerifierFromConfig(verifierConfig config.VerifierConfig, configVersio
 		if featureflag.DynamicPlugins.Enabled {
 			source, err := pluginCommon.ParsePluginSource(source)
 			if err != nil {
-				return nil, re.ErrorCodeConfigInvalid.NewError(re.Verifier, "", re.EmptyLink, err, "failed to parse plugin source", re.HideStackTrace)
+				return nil, re.ErrorCodeConfigInvalid.WithDetail("Failed to parse the plugin source").WithError(err)
 			}
 
 			targetPath := path.Join(pluginBinDir[0], verifierTypeStr)
 			err = pluginCommon.DownloadPlugin(source, targetPath)
 			if err != nil {
-				return nil, re.ErrorCodeDownloadPluginFailure.NewError(re.Verifier, "", re.EmptyLink, err, "failed to download plugin", re.HideStackTrace)
+				return nil, re.ErrorCodeDownloadPluginFailure.WithDetail("Failed to download the plugin from the source").WithError(err)
 			}
 			logrus.Infof("downloaded verifier plugin %s from %s to %s", verifierTypeStr, source.Artifact, targetPath)
 		} else {
@@ -94,7 +94,7 @@ func CreateVerifierFromConfig(verifierConfig config.VerifierConfig, configVersio
 	}
 
 	if _, err := pluginCommon.FindInPaths(verifierTypeStr, pluginBinDir); err != nil {
-		return nil, re.ErrorCodePluginNotFound.NewError(re.Verifier, "", re.EmptyLink, err, "plugin not found", re.HideStackTrace)
+		return nil, re.ErrorCodePluginNotFound.WithDetail(fmt.Sprintf("Verifier plugin %s not found", verifierTypeStr)).WithError(err).WithRemediation("Please ensure that the correct type is specified for the built-in Verifier configuration or the custom Verifier plugin is configured.")
 	}
 
 	pluginVersion := configVersion
@@ -113,11 +113,11 @@ func CreateVerifiersFromConfig(verifiersConfig config.VerifiersConfig, defaultPl
 
 	err := validateVerifiersConfig(&verifiersConfig)
 	if err != nil {
-		return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithError(err)
+		return nil, re.ErrorCodeConfigInvalid.WithError(err)
 	}
 
 	if len(verifiersConfig.Verifiers) == 0 {
-		return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail("verifiers config should have at least one verifier")
+		return nil, re.ErrorCodeConfigInvalid.WithDetail("The configuration for verifier.plugins must include at least one plugin")
 	}
 
 	verifiers := make([]verifier.ReferenceVerifier, 0)
@@ -131,7 +131,7 @@ func CreateVerifiersFromConfig(verifiersConfig config.VerifiersConfig, defaultPl
 	for _, verifierConfig := range verifiersConfig.Verifiers {
 		verifier, err := CreateVerifierFromConfig(verifierConfig, verifiersConfig.Version, verifiersConfig.PluginBinDirs, namespace)
 		if err != nil {
-			return nil, re.ErrorCodePluginInitFailure.WithComponentType(re.Verifier).WithError(err)
+			return nil, re.ErrorCodePluginInitFailure.WithError(err)
 		}
 		verifiers = append(verifiers, verifier)
 	}
diff --git a/pkg/verifier/notation/certstoresbytype.go b/pkg/verifier/notation/certstoresbytype.go
index a2ab845..a5a9228 100644
--- a/pkg/verifier/notation/certstoresbytype.go
+++ b/pkg/verifier/notation/certstoresbytype.go
@@ -73,18 +73,18 @@ func newCertStoreByType(confInNewFormat verificationCertStores) (certStores, err
 		s[certStoreType(certstoretype)] = make(map[string][]string)
 		parsedStoreData, ok := storeData.(map[string]interface{})
 		if !ok {
-			return nil, fmt.Errorf("certStores: %s assertion to type verificationCertStores failed", storeData)
+			return nil, fmt.Errorf("the verificationCertStores configuration is invalid: %+v", confInNewFormat)
 		}
 		for storeName, certProviderList := range parsedStoreData {
 			var certProviderNames []string
 			parsedCertProviders, ok := certProviderList.([]interface{})
 			if !ok {
-				return nil, fmt.Errorf("certProviderList: %s assertion to type []interface{} failed", certProviderList)
+				return nil, fmt.Errorf("the verificationCertStores configuration is invalid: %+v", confInNewFormat)
 			}
 			for _, certProvider := range parsedCertProviders {
 				certProviderName, ok := certProvider.(string)
 				if !ok {
-					return nil, fmt.Errorf("certProvider: %s assertion to type string failed", certProvider)
+					return nil, fmt.Errorf("the verificationCertStores configuration is invalid: %+v", confInNewFormat)
 				}
 				certProviderNames = append(certProviderNames, certProviderName)
 			}
diff --git a/pkg/verifier/notation/notation.go b/pkg/verifier/notation/notation.go
index 624273d..f25b21c 100644
--- a/pkg/verifier/notation/notation.go
+++ b/pkg/verifier/notation/notation.go
@@ -93,7 +93,7 @@ func init() {
 }
 
 func (f *notationPluginVerifierFactory) Create(_ string, verifierConfig config.VerifierConfig, pluginDirectory string, namespace string) (verifier.ReferenceVerifier, error) {
-	logger.GetLogger(context.Background(), logOpt).Debugf("creating notation with config %v, namespace '%v'", verifierConfig, namespace)
+	logger.GetLogger(context.Background(), logOpt).Debugf("creating Notation verifier with config %v, namespace '%v'", verifierConfig, namespace)
 	verifierName := fmt.Sprintf("%s", verifierConfig[types.Name])
 	verifierTypeStr := ""
 	if _, ok := verifierConfig[types.Type]; ok {
@@ -101,12 +101,12 @@ func (f *notationPluginVerifierFactory) Create(_ string, verifierConfig config.V
 	}
 	conf, err := parseVerifierConfig(verifierConfig, namespace)
 	if err != nil {
-		return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName)
+		return nil, re.ErrorCodePluginInitFailure.WithDetail("Failed to create the Notation Verifier").WithError(err)
 	}
 
 	verifyService, err := getVerifierService(conf, pluginDirectory)
 	if err != nil {
-		return nil, re.ErrorCodePluginInitFailure.WithComponentType(re.Verifier).WithPluginName(verifierName).WithError(err)
+		return nil, re.ErrorCodePluginInitFailure.WithDetail("Failed to create the Notation Verifier").WithError(err)
 	}
 
 	artifactTypes := strings.Split(conf.ArtifactTypes, ",")
@@ -143,22 +143,21 @@ func (v *notationPluginVerifier) Verify(ctx context.Context,
 
 	subjectDesc, err := store.GetSubjectDescriptor(ctx, subjectReference)
 	if err != nil {
-		return verifier.VerifierResult{IsSuccess: false}, re.ErrorCodeGetSubjectDescriptorFailure.NewError(re.ReferrerStore, store.Name(), re.EmptyLink, err, fmt.Sprintf("failed to resolve subject: %+v", subjectReference), re.HideStackTrace)
+		return verifier.VerifierResult{IsSuccess: false}, re.ErrorCodeVerifyReferenceFailure.WithDetail(fmt.Sprintf("Failed to validate the Notation signature of the artifact: %+v", subjectReference)).WithError(err)
 	}
 
 	referenceManifest, err := store.GetReferenceManifest(ctx, subjectReference, referenceDescriptor)
 	if err != nil {
-		return verifier.VerifierResult{IsSuccess: false}, re.ErrorCodeGetReferenceManifestFailure.NewError(re.ReferrerStore, store.Name(), re.EmptyLink, err, fmt.Sprintf("failed to resolve reference manifest: %+v", referenceDescriptor), re.HideStackTrace)
+		return verifier.VerifierResult{IsSuccess: false}, re.ErrorCodeVerifyReferenceFailure.WithDetail(fmt.Sprintf("Failed to validate the Notation signature: %+v", referenceDescriptor)).WithError(err)
 	}
 
 	if len(referenceManifest.Blobs) != 1 {
-		return verifier.VerifierResult{IsSuccess: false}, re.ErrorCodeVerifyPluginFailure.WithDetail(fmt.Sprintf("Notation signature manifest requires exactly one signature envelope blob, got %d", len(referenceManifest.Blobs))).WithRemediation(fmt.Sprintf("Please inspect the artifact [%s@%s] is correctly signed by Notation signer", subjectReference.Path, referenceDescriptor.Digest.String()))
+		return verifier.VerifierResult{IsSuccess: false}, re.ErrorCodeVerifyReferenceFailure.WithDetail(fmt.Sprintf("Notation signature manifest requires exactly one signature envelope blob, got %d", len(referenceManifest.Blobs))).WithRemediation(fmt.Sprintf("Please inspect the artifact [%s@%s] is correctly signed by Notation signer", subjectReference.Path, referenceDescriptor.Digest.String()))
 	}
-
 	blobDesc := referenceManifest.Blobs[0]
 	refBlob, err := store.GetBlobContent(ctx, subjectReference, blobDesc.Digest)
 	if err != nil {
-		return verifier.VerifierResult{IsSuccess: false}, re.ErrorCodeGetBlobContentFailure.NewError(re.ReferrerStore, store.Name(), re.EmptyLink, err, fmt.Sprintf("failed to get blob content of digest: %s", blobDesc.Digest), re.HideStackTrace)
+		return verifier.VerifierResult{IsSuccess: false}, re.ErrorCodeVerifyReferenceFailure.WithDetail(fmt.Sprintf("Failed to validate the Notation signature of the artifact: %+v", subjectReference)).WithError(err)
 	}
 
 	// TODO: notation verify API only accepts digested reference now.
@@ -166,7 +165,7 @@ func (v *notationPluginVerifier) Verify(ctx context.Context,
 	subjectRef := fmt.Sprintf("%s@%s", subjectReference.Path, subjectReference.Digest.String())
 	outcome, err := v.verifySignature(ctx, subjectRef, blobDesc.MediaType, subjectDesc.Descriptor, refBlob)
 	if err != nil {
-		return verifier.VerifierResult{IsSuccess: false, Extensions: extensions}, re.ErrorCodeVerifyPluginFailure.NewError(re.Verifier, v.name, re.NotationTsgLink, err, "failed to verify signature of digest", re.HideStackTrace)
+		return verifier.VerifierResult{IsSuccess: false, Extensions: extensions}, re.ErrorCodeVerifyReferenceFailure.WithDetail(fmt.Sprintf("Failed to validate the Notation signature: %+v", referenceDescriptor)).WithError(err)
 	}
 
 	// Note: notation verifier already validates certificate chain is not empty.
@@ -174,7 +173,7 @@ func (v *notationPluginVerifier) Verify(ctx context.Context,
 	extensions["Issuer"] = cert.Issuer.String()
 	extensions["SN"] = cert.Subject.String()
 
-	return verifier.NewVerifierResult("", v.name, v.verifierType, "Signature verification success", true, nil, extensions), nil
+	return verifier.NewVerifierResult("", v.name, v.verifierType, "Notation signature verification success", true, nil, extensions), nil
 }
 
 func getVerifierService(conf *NotationPluginVerifierConfig, pluginDirectory string) (notation.Verifier, error) {
@@ -182,7 +181,11 @@ func getVerifierService(conf *NotationPluginVerifierConfig, pluginDirectory stri
 	if err != nil {
 		return nil, err
 	}
-	return notationVerifier.New(&conf.TrustPolicyDoc, store, NewRatifyPluginManager(pluginDirectory))
+	verifier, err := notationVerifier.New(&conf.TrustPolicyDoc, store, NewRatifyPluginManager(pluginDirectory))
+	if err != nil {
+		return nil, re.ErrorCodePluginInitFailure.WithDetail("Failed to create the Notation Verifier").WithError(err)
+	}
+	return verifier, nil
 }
 
 func (v *notationPluginVerifier) verifySignature(ctx context.Context, subjectRef, mediaType string, subjectDesc oci.Descriptor, refBlob []byte) (*notation.VerificationOutcome, error) {
@@ -196,16 +199,15 @@ func (v *notationPluginVerifier) verifySignature(ctx context.Context, subjectRef
 }
 
 func parseVerifierConfig(verifierConfig config.VerifierConfig, _ string) (*NotationPluginVerifierConfig, error) {
-	verifierName := verifierConfig[types.Name].(string)
 	conf := &NotationPluginVerifierConfig{}
 
 	verifierConfigBytes, err := json.Marshal(verifierConfig)
 	if err != nil {
-		return nil, re.ErrorCodeConfigInvalid.NewError(re.Verifier, verifierName, re.EmptyLink, err, nil, re.HideStackTrace)
+		return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Failed to parse the Notation Verifier configuration: %+v", verifierConfig)).WithError(err)
 	}
 
 	if err := json.Unmarshal(verifierConfigBytes, &conf); err != nil {
-		return nil, re.ErrorCodeConfigInvalid.NewError(re.Verifier, verifierName, re.EmptyLink, err, fmt.Sprintf("failed to unmarshal to notationPluginVerifierConfig from: %+v.", verifierConfig), re.HideStackTrace)
+		return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Failed to parse the Notation Verifier configuration: %+v", verifierConfig)).WithError(err)
 	}
 
 	defaultCertsDir := paths.Join(homedir.Get(), ratifyconfig.ConfigFileDir, defaultCertPath)
@@ -235,7 +237,7 @@ func normalizeVerificationCertsStores(conf *NotationPluginVerifierConfig) error
 		}
 	}
 	if isCertStoresByType && isLegacyCertStore {
-		return re.ErrorCodeConfigInvalid.NewError(re.Verifier, conf.Name, re.EmptyLink, nil, "both old VerificationCertStores and new VerificationCertStores are provided, please provide only one", re.HideStackTrace)
+		return re.ErrorCodeConfigInvalid.WithDetail("The verificationCertStores is misconfigured with both legacy and new formats").WithRemediation("Please provide only one format for the VerificationCertStores. Refer to the Notation Verifier configuration guide: https://ratify.dev/docs/plugins/verifier/notation#configuration")
 	} else if !isCertStoresByType && isLegacyCertStore {
 		legacyCertStore, err := normalizeLegacyCertStore(conf)
 		if err != nil {
diff --git a/pkg/verifier/notation/truststore.go b/pkg/verifier/notation/truststore.go
index c7bceb4..e9490cb 100644
--- a/pkg/verifier/notation/truststore.go
+++ b/pkg/verifier/notation/truststore.go
@@ -41,7 +41,7 @@ type trustStore struct {
 func newTrustStore(certPaths []string, verificationCertStores verificationCertStores) (*trustStore, error) {
 	certStores, err := newCertStoreByType(verificationCertStores)
 	if err != nil {
-		return nil, err
+		return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Failed to create the trust store from the verificationCertStores parameter in Notation Verifier configuration: %+v", verificationCertStores)).WithError(err).WithRemediation("Please check the value of the verificationCertStores parameter according to the Notation Verifier configuration guide: https://ratify.dev/docs/plugins/verifier/notation#configuration")
 	}
 	store := &trustStore{
 		certPaths:  certPaths,


Test patch:
diff --git a/cmd/ratify/cmd/cmd_test.go b/cmd/ratify/cmd/cmd_test.go
index 9016198..f2f1b28 100644
--- a/cmd/ratify/cmd/cmd_test.go
+++ b/cmd/ratify/cmd/cmd_test.go
@@ -36,8 +36,8 @@ func TestVerify(t *testing.T) {
 
 	// TODO: make ratify cli more unit testable
 	// unit test should not have dependency for real image
-	if !strings.Contains(err.Error(), "plugin not found") {
-		t.Errorf("error expected")
+	if !strings.Contains(err.Error(), "PLUGIN_NOT_FOUND") {
+		t.Fatalf("expected containing: %s, but got: %s", "PLUGIN_NOT_FOUND", err.Error())
 	}
 }
 
diff --git a/pkg/controllers/clusterresource/verifier_controller_test.go b/pkg/controllers/clusterresource/verifier_controller_test.go
index 850a1fb..96cfb59 100644
--- a/pkg/controllers/clusterresource/verifier_controller_test.go
+++ b/pkg/controllers/clusterresource/verifier_controller_test.go
@@ -19,7 +19,6 @@ import (
 	"context"
 	"errors"
 	"os"
-	"strings"
 	"testing"
 
 	configv1beta1 "github.com/ratify-project/ratify/api/v1beta1"
@@ -124,12 +123,12 @@ func TestVerifierAdd_WithParameters(t *testing.T) {
 
 func TestVerifierAddOrReplace_PluginNotFound(t *testing.T) {
 	resetVerifierMap()
-	var resource = "invalidplugin"
-	expectedMsg := "plugin not found"
+	resource := "invalidplugin"
+	expectedMsg := "PLUGIN_NOT_FOUND: Verifier plugin pluginnotfound not found: failed to find plugin \"pluginnotfound\" in paths [test/path]: Please ensure that the correct type is specified for the built-in Verifier configuration or the custom Verifier plugin is configured."
 	var testVerifierSpec = getInvalidVerifierSpec()
 	err := verifierAddOrReplace(testVerifierSpec, resource)
 
-	if !strings.Contains(err.Error(), expectedMsg) {
+	if err.Error() != expectedMsg {
 		t.Fatalf("TestVerifierAddOrReplace_PluginNotFound expected msg: '%v', actual %v", expectedMsg, err.Error())
 	}
 }
diff --git a/pkg/controllers/namespaceresource/verifier_controller_test.go b/pkg/controllers/namespaceresource/verifier_controller_test.go
index ac433a5..5c65f16 100644
--- a/pkg/controllers/namespaceresource/verifier_controller_test.go
+++ b/pkg/controllers/namespaceresource/verifier_controller_test.go
@@ -19,7 +19,6 @@ import (
 	"context"
 	"errors"
 	"os"
-	"strings"
 	"testing"
 
 	configv1beta1 "github.com/ratify-project/ratify/api/v1beta1"
@@ -142,12 +141,12 @@ func TestVerifierAdd_WithParameters(t *testing.T) {
 
 func TestVerifierAddOrReplace_PluginNotFound(t *testing.T) {
 	resetVerifierMap()
-	var resource = "invalidplugin"
-	expectedMsg := "plugin not found"
+	resource := "invalidplugin"
+	expectedMsg := "PLUGIN_NOT_FOUND: Verifier plugin pluginnotfound not found: failed to find plugin \"pluginnotfound\" in paths [test/path]: Please ensure that the correct type is specified for the built-in Verifier configuration or the custom Verifier plugin is configured."
 	var testVerifierSpec = getInvalidVerifierSpec()
 	err := verifierAddOrReplace(testVerifierSpec, resource, testNamespace)
 
-	if !strings.Contains(err.Error(), expectedMsg) {
+	if err.Error() != expectedMsg {
 		t.Fatalf("TestVerifierAddOrReplace_PluginNotFound expected msg: '%v', actual %v", expectedMsg, err.Error())
 	}
 }
diff --git a/pkg/verifier/factory/factory_test.go b/pkg/verifier/factory/factory_test.go
index 273e76b..7b839e0 100644
--- a/pkg/verifier/factory/factory_test.go
+++ b/pkg/verifier/factory/factory_test.go
@@ -22,6 +22,7 @@ import (
 
 	"github.com/ratify-project/ratify/internal/constants"
 	"github.com/ratify-project/ratify/pkg/common"
+	"github.com/ratify-project/ratify/pkg/featureflag"
 	"github.com/ratify-project/ratify/pkg/ocispecs"
 	"github.com/ratify-project/ratify/pkg/referrerstore"
 
@@ -103,6 +104,21 @@ func TestCreateVerifiersFromConfig_BuiltInVerifiers_ReturnsExpected(t *testing.T
 	}
 }
 
+func TestCreateVerifiersFromConfig_InvalidConfig_ReturnsErr(t *testing.T) {
+	verifierConfig := map[string]interface{}{
+		"name": "test-verifier-0",
+	}
+	verifiersConfig := config.VerifiersConfig{
+		Verifiers: []config.VerifierConfig{verifierConfig},
+	}
+
+	_, err := CreateVerifiersFromConfig(verifiersConfig, "test/dir", constants.EmptyNamespace)
+
+	if err == nil {
+		t.Fatalf("expected to have an error")
+	}
+}
+
 func TestCreateVerifiersFromConfig_PluginVerifiers_ReturnsExpected(t *testing.T) {
 	dirPath, err := utils.CreatePlugin("sample")
 	if err != nil {
@@ -137,3 +153,83 @@ func TestCreateVerifiersFromConfig_PluginVerifiers_ReturnsExpected(t *testing.T)
 		t.Fatalf("type assertion failed expected a plugin in verifier")
 	}
 }
+
+func TestCreateVerifiersFromConfig_EmptyVerifiers_ReturnsErr(t *testing.T) {
+	verifiersConfig := config.VerifiersConfig{}
+
+	_, err := CreateVerifiersFromConfig(verifiersConfig, "test/dir", "")
+
+	if err == nil {
+		t.Fatalf("expected to have an error")
+	}
+}
+
+func TestCreateVerifierFromConfig(t *testing.T) {
+	tests := []struct {
+		name                 string
+		verifierConfig       config.VerifierConfig
+		configVersion        string
+		pluginBinDir         []string
+		namespace            string
+		dynamicPluginEnabled bool
+		expectedErr          bool
+	}{
+		{
+			name:           "missing name",
+			verifierConfig: config.VerifierConfig{},
+			expectedErr:    true,
+		},
+		{
+			name: "verifier type contains path separator",
+			verifierConfig: config.VerifierConfig{
+				"name": "test/verifier",
+			},
+			expectedErr: true,
+		},
+		{
+			name: "external verifier plugin not found",
+			verifierConfig: config.VerifierConfig{
+				"name": "not-found",
+			},
+			pluginBinDir: []string{"test/path"},
+			expectedErr:  true,
+		},
+		{
+			name: "parse plugin source failed",
+			verifierConfig: config.VerifierConfig{
+				"name":   "test-verifier",
+				"source": "invalid",
+			},
+			dynamicPluginEnabled: true,
+			expectedErr:          true,
+		},
+		{
+			name: "download plugin failed",
+			verifierConfig: config.VerifierConfig{
+				"name": "test-verifier",
+				"source": map[string]interface{}{
+					"artifact": "invalid",
+				},
+			},
+			pluginBinDir:         []string{"test/path"},
+			dynamicPluginEnabled: true,
+			expectedErr:          true,
+		},
+	}
+
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			if tt.dynamicPluginEnabled {
+				dynamicVal := featureflag.DynamicPlugins.Enabled
+				t.Cleanup(func() { featureflag.DynamicPlugins.Enabled = dynamicVal })
+				featureflag.DynamicPlugins.Enabled = true
+			}
+
+			_, err := CreateVerifierFromConfig(tt.verifierConfig, tt.configVersion, tt.pluginBinDir, tt.namespace)
+			if tt.expectedErr != (err != nil) {
+				t.Fatalf("expected error %v, actual %v", tt.expectedErr, err)
+			}
+		})
+	}
+}