diff --git a/core/modules/block_content/block_content.post_update.php b/core/modules/block_content/block_content.post_update.php
index 592b3ee9714733913767241e7503c5f0ce1c44f2..280d2ba59f4287f3c767db8b6374827eb267d543 100644
--- a/core/modules/block_content/block_content.post_update.php
+++ b/core/modules/block_content/block_content.post_update.php
@@ -5,6 +5,9 @@
  * Post update functions for Content Block.
  */
 
+use Drupal\Core\Config\Entity\ConfigEntityUpdater;
+use Drupal\views\ViewEntityInterface;
+
 /**
  * Implements hook_removed_post_updates().
  */
@@ -18,3 +21,27 @@ function block_content_removed_post_updates(): array {
     'block_content_post_update_revision_type' => '11.0.0',
   ];
 }
+
+/**
+ * Removes the "area_text_custom" plugin from block content view configuration.
+ */
+function block_content_post_update_10301(?array &$sandbox = NULL): int {
+  \Drupal::classResolver(ConfigEntityUpdater::class)->update($sandbox, 'view', function (ViewEntityInterface $view): bool {
+    $changed = FALSE;
+
+    foreach ($view->get('display') as $display_id => $display) {
+      if (
+        isset($display['display_options']['empty']['area_text_custom']) &&
+        $display['display_options']['empty']['area_text_custom']['content'] === 'There are no content blocks available.'
+      ) {
+        unset($display['display_options']['empty']['area_text_custom']);
+        $view->set('display.' . $display_id . '.display_options.empty.area_text_custom', NULL);
+        $changed = TRUE;
+      }
+    }
+
+    return $changed;
+  });
+
+  return 0;
+}
diff --git a/core/modules/block_content/config/optional/views.view.block_content.yml b/core/modules/block_content/config/optional/views.view.block_content.yml
index 1bccbb4464672d02b4e50c44dbd90e2437b265c0..f0f47f48b7a78ab5118a0a9676c3d4eb51724664 100644
--- a/core/modules/block_content/config/optional/views.view.block_content.yml
+++ b/core/modules/block_content/config/optional/views.view.block_content.yml
@@ -303,17 +303,6 @@ display:
         type: tag
         options: {  }
       empty:
-        area_text_custom:
-          id: area_text_custom
-          table: views
-          field: area_text_custom
-          relationship: none
-          group_type: group
-          admin_label: ''
-          plugin_id: text_custom
-          empty: true
-          content: 'There are no content blocks available.'
-          tokenize: false
         block_content_listing_empty:
           id: block_content_listing_empty
           table: block_content
diff --git a/core/modules/block_content/src/Plugin/views/area/ListingEmpty.php b/core/modules/block_content/src/Plugin/views/area/ListingEmpty.php
index b4ee4737e19bf8511a10f5b63c8cd7a3d26e9f66..c65f9cbc0e00e40cf04b893f169c0c7ec16a3215 100644
--- a/core/modules/block_content/src/Plugin/views/area/ListingEmpty.php
+++ b/core/modules/block_content/src/Plugin/views/area/ListingEmpty.php
@@ -70,19 +70,32 @@ public static function create(ContainerInterface $container, array $configuratio
    */
   public function render($empty = FALSE) {
     if (!$empty || !empty($this->options['empty'])) {
-      /** @var \Drupal\Core\Access\AccessResultInterface|\Drupal\Core\Cache\CacheableDependencyInterface $access_result */
+      $message = $this->t('There are no content blocks available.');
+
+      // Construct the "Add a content block" link
+      // only if the user has the proper access.
       $access_result = $this->accessManager->checkNamedRoute('block_content.add_page', [], $this->currentUser, TRUE);
+      if ($access_result->isAllowed()) {
+        // Only show the link if the user has permission.
+        $add_link = $this->t('Add a <a href=":url">content block</a>.', [
+          ':url' => Url::fromRoute('block_content.add_page')->toString(),
+        ]);
+        // Combine the message and the link.
+        $message .= ' ' . $add_link;
+      }
+
       $element = [
-        '#markup' => $this->t('Add a <a href=":url">content block</a>.', [':url' => Url::fromRoute('block_content.add_page')->toString()]),
-        '#access' => $access_result->isAllowed(),
+        '#markup' => $message,
         '#cache' => [
           'contexts' => $access_result->getCacheContexts(),
           'tags' => $access_result->getCacheTags(),
           'max-age' => $access_result->getCacheMaxAge(),
         ],
       ];
+
       return $element;
     }
+
     return [];
   }
 
diff --git a/core/modules/block_content/tests/src/Kernel/BlockContentUpdateTest.php b/core/modules/block_content/tests/src/Kernel/BlockContentUpdateTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..0c080706b93fcdb2592b9af25ef236307e0d9faf
--- /dev/null
+++ b/core/modules/block_content/tests/src/Kernel/BlockContentUpdateTest.php
@@ -0,0 +1,142 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\block_content\Kernel;
+
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\views\Entity\View;
+
+/**
+ * Tests the block content update hook.
+ *
+ * @group block_content
+ */
+class BlockContentUpdateTest extends KernelTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  protected static $modules = [
+    'block_content',
+    'views',
+    'user',
+    'system',
+    'config',
+  ];
+
+  /**
+   * The test view.
+   *
+   * @var \Drupal\views\Entity\View
+   */
+  protected $view;
+
+  /**
+   * Setup test environment.
+   */
+  protected function setUp(): void {
+    parent::setUp();
+
+    $this->installEntitySchema('view');
+    $this->installEntitySchema('block_content');
+    $this->installEntitySchema('user');
+    $this->installConfig(['block_content', 'views']);
+
+    // Create a test view configuration with "area_text_custom".
+    $this->view = View::create([
+      'id' => 'block_content',
+      'label' => 'Block Content Test View',
+      'module' => 'views',
+      'status' => TRUE,
+      'display' => [
+        'default' => [
+          'display_options' => [
+            'empty' => [
+              'area_text_custom' => [
+                'id' => 'text_custom',
+                'content' => 'There are no content blocks available.',
+              ],
+            ],
+          ],
+        ],
+      ],
+    ]);
+    $this->view->save();
+  }
+
+  /**
+   * Tests the update function.
+   */
+  public function testUpdateHook(): void {
+    // Ensure the plugin exists before the update.
+    $this->assertTrue(isset($this->view->get('display')['default']['display_options']['empty']['area_text_custom']));
+
+    // Run the update function with sandbox.
+    $sandbox = [];
+    block_content_post_update_10301($sandbox);
+
+    $updated_view = View::load('block_content');
+
+    // Verify the plugin is removed if it contains the default text.
+    $this->assertFalse(isset($updated_view->get('display')['default']['display_options']['empty']['area_text_custom']));
+  }
+
+  /**
+   * Tests that a customized text area is NOT removed.
+   */
+  public function testUpdateHookPreservesCustomText(): void {
+    $this->view->set('display.default.display_options.empty.area_text_custom.content', 'My custom message.');
+    $this->view->save();
+
+    $sandbox = [];
+    block_content_post_update_10301($sandbox);
+
+    $updated_view = View::load('block_content');
+
+    $this->assertTrue(isset($updated_view->get('display')['default']['display_options']['empty']['area_text_custom']));
+  }
+
+  /**
+   * Tests batch processing of multiple views.
+   */
+  public function testBatchProcessing(): void {
+    // Create additional views for batch testing.
+    for ($i = 1; $i <= 15; $i++) {
+      $view = View::create([
+        'id' => "block_content_$i",
+        'label' => "Block Content Test View $i",
+        'module' => 'views',
+        'status' => TRUE,
+        'display' => [
+          'default' => [
+            'display_options' => [
+              'empty' => [
+                'area_text_custom' => [
+                  'id' => 'text_custom',
+                  'content' => 'There are no content blocks available.',
+                ],
+              ],
+            ],
+          ],
+        ],
+      ]);
+      $view->save();
+    }
+
+    // Run the update in batches.
+    $sandbox = [];
+    do {
+      block_content_post_update_10301($sandbox);
+    } while (!empty($sandbox));
+
+    // Verify that all views have been processed.
+    for ($i = 1; $i <= 15; $i++) {
+      $updated_view = View::load("block_content_$i");
+      $this->assertFalse(isset($updated_view->get('display')['default']['display_options']['empty']['area_text_custom']));
+    }
+  }
+
+}