diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 30a530cf9eadd4b92db7349ea4d97f11a1bf14f3..0892fa26d026c822e35003f2e0f26e31ad6fa8b4 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -174,6 +174,24 @@ stages:
     _TARGET_PHP: "8.2"
     _TARGET_DB: "sqlite-3"
 
+'PHP 8.3 MySQL 8':
+  <<: [ *default-stage, *run-daily ]
+  variables:
+    _TARGET_PHP: "8.3"
+    _TARGET_DB: "mysql-8"
+
+'PHP 8.3 PostgreSQL 16':
+  <<: [ *default-stage, *run-daily ]
+  variables:
+    _TARGET_PHP: "8.3"
+    _TARGET_DB: "pgsql-16"
+
+'PHP 8.3 SQLite 3':
+  <<: [ *default-stage, *run-daily ]
+  variables:
+    _TARGET_PHP: "8.3"
+    _TARGET_DB: "sqlite-3"
+
 # Run daily, or manually.
 # 'PHP 8.1 MariaDB 10.3.22':
 #   <<: [ *default-stage, *run-daily ]
diff --git a/core/assets/scaffold/files/example.settings.local.php b/core/assets/scaffold/files/example.settings.local.php
index 7cb0e6857735d0493898ef24398b0f2617a91760..bfe061d056517140cf5fe92ed5f2dd2ff25cac2f 100644
--- a/core/assets/scaffold/files/example.settings.local.php
+++ b/core/assets/scaffold/files/example.settings.local.php
@@ -29,11 +29,7 @@
  * It is strongly recommended that you set zend.assertions=1 in the PHP.ini file
  * (It cannot be changed from .htaccess or runtime) on development machines and
  * to 0 or -1 in production.
- *
- * @see https://wiki.php.net/rfc/expectations
  */
-assert_options(ASSERT_ACTIVE, TRUE);
-assert_options(ASSERT_EXCEPTION, TRUE);
 
 /**
  * Enable local development services.
diff --git a/core/lib/Drupal/Component/Assertion/Handle.php b/core/lib/Drupal/Component/Assertion/Handle.php
index fe94bbf9d0590f619f88353c6c40df80170f80a6..da355aab30cea459fb721d04300857fb74235b13 100644
--- a/core/lib/Drupal/Component/Assertion/Handle.php
+++ b/core/lib/Drupal/Component/Assertion/Handle.php
@@ -21,9 +21,11 @@ class Handle {
    */
   public static function register() {
     // Since we're using exceptions, turn error warnings off.
+    // phpcs:ignore Generic.PHP.DeprecatedFunctions.Deprecated
     assert_options(ASSERT_WARNING, FALSE);
 
     // Turn exception throwing on.
+    // phpcs:ignore Generic.PHP.DeprecatedFunctions.Deprecated
     assert_options(ASSERT_EXCEPTION, TRUE);
   }
 
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index c6f0b9846d94290aec7ea3d5ed24e76c81d41916..dd67a2b5416f6c604b6e1062c72926107af8aff5 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -1058,11 +1058,6 @@ public static function bootEnvironment($app_root = NULL) {
         // the internal browser.
         define('DRUPAL_TEST_IN_CHILD_SITE', TRUE);
 
-        // Web tests are to be conducted with runtime assertions active.
-        assert_options(ASSERT_ACTIVE, TRUE);
-        // Force assertion failures to be thrown as exceptions.
-        assert_options(ASSERT_EXCEPTION, TRUE);
-
         // Log fatal errors to the test site directory.
         ini_set('log_errors', 1);
         ini_set('error_log', $app_root . '/' . $test_db->getTestSitePath() . '/error.log');
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index fb77dee8c2e6c8253f2286ffad90b99b54c15378..52b96742567625b154cc1d7408c9db43c09fb14e 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -469,9 +469,12 @@ public function isTranslatable() {
   public function preSave(EntityStorageInterface $storage) {
     // An entity requiring validation should not be saved if it has not been
     // actually validated.
-    assert(!$this->validationRequired || $this->validated, 'Entity validation was skipped.');
-
-    $this->validated = FALSE;
+    if ($this->validationRequired && !$this->validated) {
+      throw new \LogicException('Entity validation is required, but was skipped.');
+    }
+    else {
+      $this->validated = FALSE;
+    }
 
     parent::preSave($storage);
   }
diff --git a/core/modules/jsonapi/src/EventSubscriber/ResourceResponseValidator.php b/core/modules/jsonapi/src/EventSubscriber/ResourceResponseValidator.php
index a363e911d76ee8bc2716c26d8310c528ae9385ba..0d1d0cef219c14690bf96f41a772166b3b55b7a4 100644
--- a/core/modules/jsonapi/src/EventSubscriber/ResourceResponseValidator.php
+++ b/core/modules/jsonapi/src/EventSubscriber/ResourceResponseValidator.php
@@ -105,16 +105,8 @@ public function onResponse(ResponseEvent $event) {
       return;
     }
 
-    $this->doValidateResponse($response, $event->getRequest());
-  }
-
-  /**
-   * Wraps validation in an assert to prevent execution in production.
-   *
-   * @see self::validateResponse
-   */
-  public function doValidateResponse(Response $response, Request $request) {
-    assert($this->validateResponse($response, $request), 'A JSON:API response failed validation (see the logs for details). Report this in the issue queue on drupal.org');
+    // Wraps validation in an assert to prevent execution in production.
+    assert($this->validateResponse($response, $event->getRequest()), 'A JSON:API response failed validation (see the logs for details). Report this in the Drupal issue queue at https://www.drupal.org/project/issues/drupal');
   }
 
   /**
diff --git a/core/modules/jsonapi/tests/src/Unit/EventSubscriber/ResourceResponseValidatorTest.php b/core/modules/jsonapi/tests/src/Unit/EventSubscriber/ResourceResponseValidatorTest.php
index 7a34a41a6252a0d3df0eab283f1177051b5733b4..90b5f5f8bbd4a6c1337d22ca0268fe9605152b65 100644
--- a/core/modules/jsonapi/tests/src/Unit/EventSubscriber/ResourceResponseValidatorTest.php
+++ b/core/modules/jsonapi/tests/src/Unit/EventSubscriber/ResourceResponseValidatorTest.php
@@ -5,12 +5,10 @@
 use Drupal\jsonapi\EventSubscriber\ResourceResponseValidator;
 use Drupal\jsonapi\ResourceType\ResourceType;
 use Drupal\jsonapi\Routing\Routes;
-use JsonSchema\Validator;
 use Drupal\Core\Extension\Extension;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\rest\ResourceResponse;
 use Drupal\Tests\UnitTestCase;
-use Prophecy\Argument;
 use Psr\Log\LoggerInterface;
 use Drupal\Core\Routing\RouteObjectInterface;
 use Symfony\Component\HttpFoundation\Request;
@@ -54,47 +52,6 @@ protected function setUp(): void {
     $this->subscriber = $subscriber;
   }
 
-  /**
-   * @covers ::doValidateResponse
-   */
-  public function testDoValidateResponse() {
-    $request = $this->createRequest(
-      'jsonapi.node--article.individual',
-      new ResourceType('node', 'article', NULL)
-    );
-
-    $response = $this->createResponse('{"data":null}');
-
-    // Capture the default assert settings.
-    $zend_assertions_default = ini_get('zend.assertions');
-    $assert_active_default = assert_options(ASSERT_ACTIVE);
-
-    // The validator *should* be called when asserts are active.
-    $validator = $this->prophesize(Validator::class);
-    $validator->check(Argument::any(), Argument::any())->shouldBeCalled('Validation should be run when asserts are active.');
-    $validator->isValid()->willReturn(TRUE);
-    $this->subscriber->setValidator($validator->reveal());
-
-    // Ensure asset is active.
-    ini_set('zend.assertions', 1);
-    assert_options(ASSERT_ACTIVE, 1);
-    $this->subscriber->doValidateResponse($response, $request);
-
-    // The validator should *not* be called when asserts are inactive.
-    $validator = $this->prophesize(Validator::class);
-    $validator->check(Argument::any(), Argument::any())->shouldNotBeCalled('Validation should not be run when asserts are not active.');
-    $this->subscriber->setValidator($validator->reveal());
-
-    // Ensure asset is inactive.
-    ini_set('zend.assertions', 0);
-    assert_options(ASSERT_ACTIVE, 0);
-    $this->subscriber->doValidateResponse($response, $request);
-
-    // Reset the original assert values.
-    ini_set('zend.assertions', $zend_assertions_default);
-    assert_options(ASSERT_ACTIVE, $assert_active_default);
-  }
-
   /**
    * @covers ::validateResponse
    * @dataProvider validateResponseProvider
diff --git a/core/modules/system/tests/modules/entity_test/src/EntityTestForm.php b/core/modules/system/tests/modules/entity_test/src/EntityTestForm.php
index 4ec687aacd96c055e3a809535c20f98e62302e60..3ea354d54993f929c25c1b625660fdd96896582f 100644
--- a/core/modules/system/tests/modules/entity_test/src/EntityTestForm.php
+++ b/core/modules/system/tests/modules/entity_test/src/EntityTestForm.php
@@ -80,7 +80,7 @@ public function save(array $form, FormStateInterface $form_state) {
         $form_state->setRebuild();
       }
     }
-    catch (\AssertionError $e) {
+    catch (\Exception $e) {
       \Drupal::state()->set('entity_test.form.save.exception', get_class($e) . ': ' . $e->getMessage());
     }
     return $status ?? FALSE;
diff --git a/core/modules/system/tests/src/Functional/Entity/EntityFormTest.php b/core/modules/system/tests/src/Functional/Entity/EntityFormTest.php
index a9ce73618169517c995dd38f079012ef20515d4f..930636ac59c1826c1bd8d3df90c1007d4d64c97a 100644
--- a/core/modules/system/tests/src/Functional/Entity/EntityFormTest.php
+++ b/core/modules/system/tests/src/Functional/Entity/EntityFormTest.php
@@ -229,7 +229,7 @@ public function testValidationHandlers() {
     $state->set('entity_test.form.validate.test', 'button-level');
     $this->drupalGet('entity_test/add');
     $this->submitForm([], 'Save');
-    $this->assertEquals('AssertionError: Entity validation was skipped.', $state->get('entity_test.form.save.exception'), 'Button-level validation handlers behave correctly.');
+    $this->assertEquals('Drupal\\Core\\Entity\\EntityStorageException: Entity validation is required, but was skipped.', $state->get('entity_test.form.save.exception'), 'Button-level validation handlers behave correctly.');
   }
 
   /**
diff --git a/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php
index 8b75f404e7155aea16d364994288bb58b7dfbc85..38908b9aa605665bb3b1a865e07c2a64c66fee57 100644
--- a/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php
@@ -489,8 +489,8 @@ public function testRequiredValidation() {
     // that trying to save a non-validated entity when validation is required
     // results in an exception.
     $this->assertTrue($this->entity->isValidationRequired());
-    $this->expectException(\AssertionError::class);
-    $this->expectExceptionMessage('Entity validation was skipped.');
+    $this->expectException(\LogicException::class);
+    $this->expectExceptionMessage('Entity validation is required, but was skipped.');
     $this->entity->save();
   }
 
diff --git a/core/tests/Drupal/Tests/Core/Field/FieldTypePluginManagerTest.php b/core/tests/Drupal/Tests/Core/Field/FieldTypePluginManagerTest.php
index ac286f245656c64b7c679b0248ac2b9dabdf4af3..b0253acc06e56ed4fe2ae21fd961958d8762e901 100644
--- a/core/tests/Drupal/Tests/Core/Field/FieldTypePluginManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Field/FieldTypePluginManagerTest.php
@@ -147,17 +147,14 @@ public function testGetGroupedDefinitionsInvalid() {
     ]);
 
     $zend_assertions_default = ini_get('zend.assertions');
-    $assert_active_default = assert_options(ASSERT_ACTIVE);
 
     // Test behavior when assertions are not enabled.
     ini_set('zend.assertions', 0);
-    assert_options(ASSERT_ACTIVE, 0);
     $grouped_definitions = $this->fieldTypeManager->getGroupedDefinitions();
     $this->assertEquals(['General'], array_keys($grouped_definitions));
 
     // Test behavior when assertions are enabled.
     ini_set('zend.assertions', 1);
-    assert_options(ASSERT_ACTIVE, 1);
     $this->expectException(\AssertionError::class);
     try {
       $this->fieldTypeManager->getGroupedDefinitions();
@@ -165,7 +162,6 @@ public function testGetGroupedDefinitionsInvalid() {
     catch (\Exception $e) {
       // Reset the original assert values.
       ini_set('zend.assertions', $zend_assertions_default);
-      assert_options(ASSERT_ACTIVE, $assert_active_default);
 
       throw $e;
     }
diff --git a/core/tests/bootstrap.php b/core/tests/bootstrap.php
index 295abc42659b33cee336b494dced70d959457e1d..0ea13b0f3937ce4378191810fb2828f998bb8a01 100644
--- a/core/tests/bootstrap.php
+++ b/core/tests/bootstrap.php
@@ -173,11 +173,6 @@ class_alias('\Drupal\Tests\DocumentElement', '\Behat\Mink\Element\DocumentElemen
 // reduce the fragility of the testing system in general.
 date_default_timezone_set('Australia/Sydney');
 
-// Runtime assertions. PHPUnit follows the php.ini assert.active setting for
-// runtime assertions. By default this setting is on. Ensure exceptions are
-// thrown if an assert fails.
-assert_options(ASSERT_EXCEPTION, TRUE);
-
 // Ensure ignored deprecation patterns listed in .deprecation-ignore.txt are
 // considered in testing.
 if (getenv('SYMFONY_DEPRECATIONS_HELPER') === FALSE) {
diff --git a/sites/example.settings.local.php b/sites/example.settings.local.php
index 7cb0e6857735d0493898ef24398b0f2617a91760..bfe061d056517140cf5fe92ed5f2dd2ff25cac2f 100644
--- a/sites/example.settings.local.php
+++ b/sites/example.settings.local.php
@@ -29,11 +29,7 @@
  * It is strongly recommended that you set zend.assertions=1 in the PHP.ini file
  * (It cannot be changed from .htaccess or runtime) on development machines and
  * to 0 or -1 in production.
- *
- * @see https://wiki.php.net/rfc/expectations
  */
-assert_options(ASSERT_ACTIVE, TRUE);
-assert_options(ASSERT_EXCEPTION, TRUE);
 
 /**
  * Enable local development services.