diff --git a/temporal-sdk/src/main/java/io/temporal/common/converter/PayloadValidationException.java b/temporal-sdk/src/main/java/io/temporal/common/converter/PayloadValidationException.java
new file mode 100644
index 0000000000..459c2a4132
--- /dev/null
+++ b/temporal-sdk/src/main/java/io/temporal/common/converter/PayloadValidationException.java
@@ -0,0 +1,23 @@
+package io.temporal.common.converter;
+
+import io.temporal.failure.ApplicationFailure;
+
+/** Factory for failures raised when converting a value that violates its payload schema. */
+public final class PayloadValidationException {
+ private static final String MESSAGE = "Payload validation failed";
+ private static final String TYPE = "PayloadValidationError";
+
+ private PayloadValidationException() {}
+
+ /**
+ * Creates a non-retryable failure containing payload validation details.
+ *
+ *
The details are stored as a single value and serialized by the configured {@link
+ * DataConverter}.
+ *
+ * @param details payload validation details
+ */
+ public static ApplicationFailure newPayloadValidationException(Object details) {
+ return ApplicationFailure.newNonRetryableFailure(MESSAGE, TYPE, details);
+ }
+}
diff --git a/temporal-sdk/src/test/java/io/temporal/common/converter/PayloadValidationExceptionTest.java b/temporal-sdk/src/test/java/io/temporal/common/converter/PayloadValidationExceptionTest.java
new file mode 100644
index 0000000000..bca471d72b
--- /dev/null
+++ b/temporal-sdk/src/test/java/io/temporal/common/converter/PayloadValidationExceptionTest.java
@@ -0,0 +1,39 @@
+package io.temporal.common.converter;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.reflect.TypeToken;
+import io.temporal.api.failure.v1.Failure;
+import io.temporal.failure.ApplicationFailure;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.junit.Test;
+
+public class PayloadValidationExceptionTest {
+ @Test
+ public void
+ newPayloadValidationExceptionReturnsNonRetryableApplicationFailureWithEncodedDetails() {
+ List