diff --git a/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php b/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php
index 29efd63f7e477ca7beec8b096551e10c5112c89b..b0ac7dbd3be20c73eef091d5e1e243911286a606 100644
--- a/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php
+++ b/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php
@@ -93,8 +93,16 @@ public function validate($data, $constraints = NULL, $groups = NULL, $is_root_ca
       throw new \LogicException('Passing custom groups is not supported.');
     }
 
+    // Convert to TypedDataInterface if it matches the context object's value
     if (!$data instanceof TypedDataInterface) {
-      throw new \InvalidArgumentException('The passed value must be a typed data object.');
+      $context_object = $this->context->getObject();
+
+      if ($context_object instanceof TypedDataInterface && $data === $context_object->getValue()) {
+        $data = $context_object;
+      }
+      else {
+        throw new \InvalidArgumentException('The passed value must be a typed data object.');
+      }
     }
 
     // You can pass a single constraint or an array of constraints.
diff --git a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/SequentiallyConstraint.php b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/SequentiallyConstraint.php
new file mode 100644
index 0000000000000000000000000000000000000000..aefd2354fb0261b3c41be48ccd4311c1524b394a
--- /dev/null
+++ b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/SequentiallyConstraint.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Drupal\Core\Validation\Plugin\Validation\Constraint;
+
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\Core\Validation\Attribute\Constraint;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\Validator\Constraint as SymfonyConstraint;
+use Symfony\Component\Validator\Constraints\Sequentially;
+
+/**
+ * Checks constraints sequentially and shows the error from the first.
+ */
+#[Constraint(
+  id: 'Sequentially',
+  label: new TranslatableMarkup('Sequentially validate', [], ['context' => 'Validation'])
+)]
+class SequentiallyConstraint extends Sequentially implements ContainerFactoryPluginInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    $constraint_manager = $container->get('validation.constraint');
+    $constraints = $configuration['constraints'];
+    $constraint_instances = [];
+    foreach ($constraints as $constraint_id => $constraint) {
+      foreach ($constraint as $constraint_name => $constraint_options) {
+        $constraint_instances[$constraint_id] = $constraint_manager->create($constraint_name, $constraint_options);
+      }
+    }
+
+    return new static($constraint_instances, [SymfonyConstraint::DEFAULT_GROUP]);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/SequentiallyConstraintValidator.php b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/SequentiallyConstraintValidator.php
new file mode 100644
index 0000000000000000000000000000000000000000..b3b113a6f73f43b915a19d400a5c49664b8f3c1f
--- /dev/null
+++ b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/SequentiallyConstraintValidator.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Drupal\Core\Validation\Plugin\Validation\Constraint;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\Constraints\SequentiallyValidator;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * Validates the Sequentially constraint.
+ */
+class SequentiallyConstraintValidator extends SequentiallyValidator {
+
+  /**
+   * Validate a set of constraints against a value sequentially.
+   *
+   * @param mixed $value
+   *   The value to validate.
+   * @param \Symfony\Component\Validator\Constraint $constraint
+   *   The constraint to validate against.
+   */
+  public function validate(mixed $value, Constraint $constraint): void {
+    if (!$constraint instanceof SequentiallyConstraint) {
+      throw new UnexpectedTypeException($constraint, SequentiallyConstraint::class);
+    }
+
+    parent::validate($value, $constraint);
+  }
+
+}
diff --git a/core/tests/Drupal/KernelTests/Core/Validation/SequentiallyConstraintValidatorTest.php b/core/tests/Drupal/KernelTests/Core/Validation/SequentiallyConstraintValidatorTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f6c1a1d8760bdd8a0001b7b25716f668b738d906
--- /dev/null
+++ b/core/tests/Drupal/KernelTests/Core/Validation/SequentiallyConstraintValidatorTest.php
@@ -0,0 +1,105 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\KernelTests\Core\Validation;
+
+use Drupal\Core\TypedData\DataDefinition;
+use Drupal\Core\TypedData\TypedDataManagerInterface;
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * Tests Sequentially validation constraint with both valid and invalid values.
+ *
+ * @covers \Drupal\Core\Validation\Plugin\Validation\Constraint\SequentiallyConstraint
+ * @covers \Drupal\Core\Validation\Plugin\Validation\Constraint\SequentiallyConstraintValidator
+ *
+ * @group Validation
+ */
+class SequentiallyConstraintValidatorTest extends KernelTestBase {
+
+  /**
+   * The typed data manager to use.
+   */
+  protected TypedDataManagerInterface $typedData;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+    $this->typedData = $this->container->get('typed_data_manager');
+  }
+
+  /**
+   * Tests the Sequentially validation constraint validator.
+   *
+   * @dataProvider dataProvider
+   */
+  public function testValidation(string $type, mixed $value, array $constraints, array $expectedViolations, array $extra_constraints = []): void {
+    // Create a definition that specifies some AllowedValues.
+    $definition = DataDefinition::create($type);
+
+    if (count($extra_constraints) > 0) {
+      foreach ($extra_constraints as $name => $settings) {
+        $definition->addConstraint($name, $settings);
+      }
+    }
+
+    $definition->addConstraint('Sequentially', [
+      'constraints' => $constraints,
+    ]);
+
+    // Test the validation.
+    $typed_data = $this->typedData->create($definition, $value);
+    $violations = $typed_data->validate();
+
+    $violationMessages = [];
+    foreach ($violations as $violation) {
+      $violationMessages[] = (string) $violation->getMessage();
+    }
+
+    $this->assertEquals($expectedViolations, $violationMessages, 'Validation passed for correct value.');
+  }
+
+  /**
+   * Data provider for testValidation().
+   */
+  public static function dataProvider(): array {
+    return [
+      'It should fail on a failing sibling validator' => [
+        'integer',
+        150,
+        [
+          ['Range' => ['min' => 100]],
+          ['NotNull' => []],
+        ],
+        ['This value should be blank.'],
+        ['Blank' => []],
+      ],
+      'it should fail if second validator fails' => [
+        'integer',
+        250,
+        [
+          ['Range' => ['min' => 100]],
+          ['AllowedValues' => [500]],
+        ],
+        [
+          'The value you selected is not a valid choice.',
+        ],
+      ],
+      'it should show first validation error only even when multiple would fail' => [
+        'string',
+        'Green',
+        [
+          ['AllowedValues' => ['test']],
+          ['Blank' => []],
+        ],
+        [
+          'The value you selected is not a valid choice.',
+        ],
+      ],
+    ];
+  }
+
+}