diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index b5acdd55f3..a57c83c958 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -15,6 +15,7 @@ Changelog
  * Fix: InlinePanel add button is now keyboard navigatable (Jesse Menn)
  * Fix: Remove redundant 'clear' button from site root page chooser (Matt Westcott)
  * Fix: Make ModelAdmin IndexView keyboard-navigable (Saptak Sengupta)
+ * Fix: Prevent error on refreshing page previews when multiple preview tabs are open (Alex Tomkins)
 
 
 2.14.1 (12.08.2021)
diff --git a/docs/releases/2.15.rst b/docs/releases/2.15.rst
index 5ea5d5b3e5..bd0baa8537 100644
--- a/docs/releases/2.15.rst
+++ b/docs/releases/2.15.rst
@@ -31,6 +31,7 @@ Bug fixes
  * InlinePanel add button is now keyboard navigatable (Jesse Menn)
  * Remove redundant 'clear' button from site root page chooser (Matt Westcott)
  * Make ModelAdmin IndexView keyboard-navigable (Saptak Sengupta)
+ * Prevent error on refreshing page previews when multiple preview tabs are open (Alex Tomkins)
 
 Upgrade considerations
 ======================
diff --git a/wagtail/admin/tests/pages/test_preview.py b/wagtail/admin/tests/pages/test_preview.py
index dca53d5f18..2018df3ae5 100644
--- a/wagtail/admin/tests/pages/test_preview.py
+++ b/wagtail/admin/tests/pages/test_preview.py
@@ -112,6 +112,10 @@ class TestPreview(TestCase, WagtailTestUtils):
         self.assertEqual(response.status_code, 200)
         self.assertJSONEqual(response.content.decode(), {'is_valid': True})
 
+        # Check the user can refresh the preview
+        preview_session_key = 'wagtail-preview-tests-eventpage-{}'.format(self.home_page.id)
+        self.assertTrue(preview_session_key in self.client.session)
+
         response = self.client.get(preview_url)
 
         # Check the HTML response
@@ -130,6 +134,10 @@ class TestPreview(TestCase, WagtailTestUtils):
         self.assertEqual(response.status_code, 200)
         self.assertJSONEqual(response.content.decode(), {'is_valid': True})
 
+        # Check the user can refresh the preview
+        preview_session_key = 'wagtail-preview-{}'.format(self.event_page.id)
+        self.assertTrue(preview_session_key in self.client.session)
+
         response = self.client.get(preview_url)
 
         # Check the HTML response
diff --git a/wagtail/admin/views/pages/preview.py b/wagtail/admin/views/pages/preview.py
index ae4e29675e..ea9cbac451 100644
--- a/wagtail/admin/views/pages/preview.py
+++ b/wagtail/admin/views/pages/preview.py
@@ -41,7 +41,7 @@ class PreviewOnEdit(View):
 
     @property
     def session_key(self):
-        return self.session_key_prefix + ','.join(self.args)
+        return '{}{}'.format(self.session_key_prefix, self.kwargs['page_id'])
 
     def get_page(self):
         return get_object_or_404(Page,
@@ -93,6 +93,15 @@ class PreviewOnEdit(View):
 
 
 class PreviewOnCreate(PreviewOnEdit):
+    @property
+    def session_key(self):
+        return '{}{}-{}-{}'.format(
+            self.session_key_prefix,
+            self.kwargs['content_type_app_name'],
+            self.kwargs['content_type_model_name'],
+            self.kwargs['parent_page_id'],
+        )
+
     def get_page(self):
         content_type_app_name = self.kwargs["content_type_app_name"]
         content_type_model_name = self.kwargs["content_type_model_name"]