diff --git a/tests/data/virtual-server-error-pages/standard/virtual-server.yaml b/tests/data/virtual-server-error-pages/standard/virtual-server.yaml
new file mode 100644
index 0000000000..dc622fc951
--- /dev/null
+++ b/tests/data/virtual-server-error-pages/standard/virtual-server.yaml
@@ -0,0 +1,35 @@
+apiVersion: k8s.nginx.org/v1
+kind: VirtualServer
+metadata:
+  name: virtual-server
+spec:
+  host: virtual-server.example.com
+  upstreams:
+  - name: backend2
+    service: backend2-svc
+    port: 80
+  - name: backend1
+    service: backend1-svc
+    port: 80
+  routes:
+  - path: "/backend1"
+    errorPages:
+      - codes: [502]
+        redirect:
+          code: 307
+          url: ${scheme}://virtual-server.example.com/error.html
+    action:
+      pass: backend1
+  - path: "/backend2"
+    errorPages:
+      - codes: [502]
+        return:
+          code: 207
+          type: application/json
+          body: |
+            {\"status\": \"${upstream_status}\",\"message\":\"Forbidden\"}
+          headers:
+          - name: x-debug-original-status
+            value: ${upstream_status}
+    action:
+      pass: backend2
\ No newline at end of file
diff --git a/tests/data/virtual-server-error-pages/virtual-server-invalid.yaml b/tests/data/virtual-server-error-pages/virtual-server-invalid.yaml
new file mode 100644
index 0000000000..177615f52e
--- /dev/null
+++ b/tests/data/virtual-server-error-pages/virtual-server-invalid.yaml
@@ -0,0 +1,35 @@
+apiVersion: k8s.nginx.org/v1
+kind: VirtualServer
+metadata:
+  name: virtual-server
+spec:
+  host: virtual-server.example.com
+  upstreams:
+  - name: backend2
+    service: backend2-svc
+    port: 80
+  - name: backend1
+    service: backend1-svc
+    port: 80
+  routes:
+  - path: "/backend1"
+    errorPages:
+      - codes: [308]
+        redirect:
+          code: 101
+          url: /relative/path/url.html
+    action:
+      pass: backend1
+  - path: "/backend2"
+    errorPages:
+      - codes: [502]
+        return:
+          code: 100
+          type: ±!@£$%^&*()
+          body: |
+            {\"status\": \"${status}\",\"message\":\"Forbidden\"}
+          headers:
+          - name: x-debug-original-status
+            value: ${schema}
+    action:
+      pass: backend2
\ No newline at end of file
diff --git a/tests/data/virtual-server-error-pages/virtual-server-matches.yaml b/tests/data/virtual-server-error-pages/virtual-server-matches.yaml
new file mode 100644
index 0000000000..f9bac75974
--- /dev/null
+++ b/tests/data/virtual-server-error-pages/virtual-server-matches.yaml
@@ -0,0 +1,52 @@
+apiVersion: k8s.nginx.org/v1
+kind: VirtualServer
+metadata:
+  name: virtual-server
+spec:
+  host: virtual-server.example.com
+  upstreams:
+  - name: backend2
+    service: backend2-svc
+    port: 80
+  - name: backend4-stable
+    service: backend4-stable-svc
+    port: 80
+  - name: backend1-future
+    service: backend1-future-svc
+    port: 80
+  - name: backend3-deprecated
+    service: backend3-deprecated-svc
+    port: 80
+  routes:
+  - path: "/backend1"
+    matches:
+      - conditions:
+          - header: x-version
+            value: future
+        action:
+          pass: backend1-future
+      - conditions:
+          - header: x-version
+            value: deprecated
+        action:
+          pass: backend3-deprecated
+    action:
+      pass: backend4-stable
+    errorPages:
+      - codes: [502, 404]
+        redirect:
+          code: 307
+          url: ${scheme}://virtual-server.example.com/error.html
+  - path: "/backend2"
+    errorPages:
+      - codes: [502]
+        return:
+          code: 207
+          type: application/json
+          body: |
+            {\"status\": \"${upstream_status}\",\"message\":\"Forbidden\"}
+          headers:
+          - name: x-debug-original-status
+            value: ${upstream_status}
+    action:
+      pass: backend2
\ No newline at end of file
diff --git a/tests/data/virtual-server-error-pages/virtual-server-splits.yaml b/tests/data/virtual-server-error-pages/virtual-server-splits.yaml
new file mode 100644
index 0000000000..2c1c5bf7d8
--- /dev/null
+++ b/tests/data/virtual-server-error-pages/virtual-server-splits.yaml
@@ -0,0 +1,43 @@
+apiVersion: k8s.nginx.org/v1
+kind: VirtualServer
+metadata:
+  name: virtual-server
+spec:
+  host: virtual-server.example.com
+  upstreams:
+  - name: backend2
+    service: backend2-svc
+    port: 80
+  - name: backend1-v1
+    service: backend1-svc-v1
+    port: 80
+  - name: backend1-v2
+    service: backend1-svc-v2
+    port: 80
+  routes:
+  - path: "/backend1"
+    splits:
+      - weight: 90
+        action:
+          pass: backend1-v1
+      - weight: 10
+        action:
+          pass: backend1-v2
+    errorPages:
+      - codes: [502]
+        redirect:
+          code: 308
+          url: ${scheme}://virtual-server.example.com/error.html
+  - path: "/backend2"
+    errorPages:
+      - codes: [502]
+        return:
+          code: 207
+          type: application/json
+          body: |
+            {\"status\": \"${upstream_status}\",\"message\":\"Forbidden\"}
+          headers:
+          - name: x-debug-original-status
+            value: ${upstream_status}
+    action:
+      pass: backend2
\ No newline at end of file
diff --git a/tests/data/virtual-server-error-pages/virtual-server-updated.yaml b/tests/data/virtual-server-error-pages/virtual-server-updated.yaml
new file mode 100644
index 0000000000..804f572a8d
--- /dev/null
+++ b/tests/data/virtual-server-error-pages/virtual-server-updated.yaml
@@ -0,0 +1,29 @@
+apiVersion: k8s.nginx.org/v1
+kind: VirtualServer
+metadata:
+  name: virtual-server
+spec:
+  host: virtual-server.example.com
+  upstreams:
+  - name: backend2
+    service: backend2-svc
+    port: 80
+  - name: backend1
+    service: backend1-svc
+    port: 80
+  routes:
+  - path: "/backend1"
+    errorPages:
+      - codes: [502, 404]
+        redirect:
+          url: ${scheme}://virtual-server.example.com/error_${http_x_forwarded_proto}.html
+    action:
+      pass: backend1
+  - path: "/backend2"
+    errorPages:
+      - codes: [502]
+        return:
+          body: |
+            Hello World!
+    action:
+      pass: backend2
\ No newline at end of file
diff --git a/tests/data/virtual-server-route-error-pages/route-multiple-invalid.yaml b/tests/data/virtual-server-route-error-pages/route-multiple-invalid.yaml
new file mode 100644
index 0000000000..9866aae68f
--- /dev/null
+++ b/tests/data/virtual-server-route-error-pages/route-multiple-invalid.yaml
@@ -0,0 +1,35 @@
+apiVersion: k8s.nginx.org/v1
+kind: VirtualServerRoute
+metadata:
+  name: backends
+spec:
+  host: virtual-server-route.example.com
+  upstreams:
+  - name: backend1
+    service: backend1-svc
+    port: 80
+  - name: backend3
+    service: backend3-svc
+    port: 80
+  subroutes:
+  - path: "/backends/backend1"
+    errorPages:
+      - codes: [308]
+        redirect:
+          code: 101
+          url: /relative/path/url.html
+    action:
+      pass: backend1
+  - path: "/backends/backend3"
+    errorPages:
+      - codes: [502]
+        return:
+          code: 100
+          type: ±!@£$%^&*()
+          body: |
+            {\"status\": \"${status}\",\"message\":\"Forbidden\"}
+          headers:
+          - name: x-debug-original-status
+            value: ${schema}
+    action:
+      pass: backend3
\ No newline at end of file
diff --git a/tests/data/virtual-server-route-error-pages/route-multiple-matches.yaml b/tests/data/virtual-server-route-error-pages/route-multiple-matches.yaml
new file mode 100644
index 0000000000..b659f5887d
--- /dev/null
+++ b/tests/data/virtual-server-route-error-pages/route-multiple-matches.yaml
@@ -0,0 +1,52 @@
+apiVersion: k8s.nginx.org/v1
+kind: VirtualServerRoute
+metadata:
+  name: backends
+spec:
+  host: virtual-server-route.example.com
+  upstreams:
+  - name: backend1
+    service: backend1-svc
+    port: 80
+  - name: backend4-stable
+    service: backend4-stable-svc
+    port: 80
+  - name: backend1-future
+    service: backend1-future-svc
+    port: 80
+  - name: backend3-deprecated
+    service: backend3-deprecated-svc
+    port: 80
+  subroutes:
+  - path: "/backends/backend1"
+    matches:
+      - conditions:
+          - argument: arg1
+            value: v1
+        action:
+          pass: backend1-future
+      - conditions:
+          - argument: arg1
+            value: v2
+        action:
+          pass: backend3-deprecated
+    errorPages:
+      - codes: [502, 404]
+        redirect:
+          code: 307
+          url: ${scheme}://virtual-server-route.example.com/error.html
+    action:
+      pass: backend4-stable
+  - path: "/backends/backend3"
+    errorPages:
+      - codes: [502]
+        return:
+          code: 207
+          type: application/json
+          body: |
+            {\"status\": \"${upstream_status}\",\"message\":\"Forbidden\"}
+          headers:
+            - name: x-debug-original-status
+              value: ${upstream_status}
+    action:
+      pass: backend3-deprecated
\ No newline at end of file
diff --git a/tests/data/virtual-server-route-error-pages/route-multiple-splits.yaml b/tests/data/virtual-server-route-error-pages/route-multiple-splits.yaml
new file mode 100644
index 0000000000..62e0f2a917
--- /dev/null
+++ b/tests/data/virtual-server-route-error-pages/route-multiple-splits.yaml
@@ -0,0 +1,43 @@
+apiVersion: k8s.nginx.org/v1
+kind: VirtualServerRoute
+metadata:
+  name: backends
+spec:
+  host: virtual-server-route.example.com
+  upstreams:
+  - name: backend1-v1
+    service: backend1-svc-v1
+    port: 80
+  - name: backend1-v2
+    service: backend1-svc-v2
+    port: 80
+  - name: backend3
+    service: backend3-svc
+    port: 80
+  subroutes:
+  - path: "/backends/backend1"
+    splits:
+      - weight: 90
+        action:
+          pass: backend1-v1
+      - weight: 10
+        action:
+          pass: backend1-v2
+    errorPages:
+      - codes: [502]
+        redirect:
+          code: 308
+          url: ${scheme}://virtual-server-route.example.com/error.html
+  - path: "/backends/backend3"
+    errorPages:
+      - codes: [502]
+        return:
+          code: 207
+          type: application/json
+          body: |
+            {\"status\": \"${upstream_status}\",\"message\":\"Forbidden\"}
+          headers:
+            - name: x-debug-original-status
+              value: ${upstream_status}
+    action:
+      pass: backend3
\ No newline at end of file
diff --git a/tests/data/virtual-server-route-error-pages/route-multiple-updated.yaml b/tests/data/virtual-server-route-error-pages/route-multiple-updated.yaml
new file mode 100644
index 0000000000..fec87d9072
--- /dev/null
+++ b/tests/data/virtual-server-route-error-pages/route-multiple-updated.yaml
@@ -0,0 +1,29 @@
+apiVersion: k8s.nginx.org/v1
+kind: VirtualServerRoute
+metadata:
+  name: backends
+spec:
+  host: virtual-server-route.example.com
+  upstreams:
+  - name: backend1
+    service: backend1-svc
+    port: 80
+  - name: backend3
+    service: backend3-svc
+    port: 80
+  subroutes:
+  - path: "/backends/backend1"
+    errorPages:
+      - codes: [502, 404]
+        redirect:
+          url: ${scheme}://virtual-server-route.example.com/error_${http_x_forwarded_proto}.html
+    action:
+      pass: backend1
+  - path: "/backends/backend3"
+    errorPages:
+      - codes: [502]
+        return:
+          body: |
+            Hello World!
+    action:
+      pass: backend3
\ No newline at end of file
diff --git a/tests/data/virtual-server-route-error-pages/route-multiple.yaml b/tests/data/virtual-server-route-error-pages/route-multiple.yaml
new file mode 100644
index 0000000000..4da8b4d7ed
--- /dev/null
+++ b/tests/data/virtual-server-route-error-pages/route-multiple.yaml
@@ -0,0 +1,35 @@
+apiVersion: k8s.nginx.org/v1
+kind: VirtualServerRoute
+metadata:
+  name: backends
+spec:
+  host: virtual-server-route.example.com
+  upstreams:
+  - name: backend1
+    service: backend1-svc
+    port: 80
+  - name: backend3
+    service: backend3-svc
+    port: 80
+  subroutes:
+  - path: "/backends/backend1"
+    errorPages:
+      - codes: [502]
+        redirect:
+          code: 307
+          url: ${scheme}://virtual-server-route.example.com/error.html
+    action:
+      pass: backend1
+  - path: "/backends/backend3"
+    errorPages:
+      - codes: [502]
+        return:
+          code: 207
+          type: application/json
+          body: |
+            {\"status\": \"${upstream_status}\",\"message\":\"Forbidden\"}
+          headers:
+            - name: x-debug-original-status
+              value: ${upstream_status}
+    action:
+      pass: backend3
\ No newline at end of file
diff --git a/tests/data/virtual-server-route-error-pages/route-single-invalid.yaml b/tests/data/virtual-server-route-error-pages/route-single-invalid.yaml
new file mode 100644
index 0000000000..32494ec93e
--- /dev/null
+++ b/tests/data/virtual-server-route-error-pages/route-single-invalid.yaml
@@ -0,0 +1,19 @@
+apiVersion: k8s.nginx.org/v1
+kind: VirtualServerRoute
+metadata:
+  name: backend2
+spec:
+  host: virtual-server-route.example.com
+  upstreams:
+  - name: backend2
+    service: backend2-svc
+    port: 80
+  subroutes:
+  - path: "/backend2"
+    errorPages:
+      - codes: [502]
+        redirect:
+          code: 307
+          url:
+    action:
+      pass: backend2
\ No newline at end of file
diff --git a/tests/data/virtual-server-route-error-pages/route-single.yaml b/tests/data/virtual-server-route-error-pages/route-single.yaml
new file mode 100644
index 0000000000..f18b2cc1d1
--- /dev/null
+++ b/tests/data/virtual-server-route-error-pages/route-single.yaml
@@ -0,0 +1,19 @@
+apiVersion: k8s.nginx.org/v1
+kind: VirtualServerRoute
+metadata:
+  name: backend2
+spec:
+  host: virtual-server-route.example.com
+  upstreams:
+  - name: backend2
+    service: backend2-svc
+    port: 80
+  subroutes:
+  - path: "/backend2"
+    errorPages:
+      - codes: [502]
+        redirect:
+          code: 307
+          url: ${scheme}://virtual-server.example.com/error.html
+    action:
+      pass: backend2
\ No newline at end of file
diff --git a/tests/data/virtual-server-route-error-pages/standard/virtual-server-updated.yaml b/tests/data/virtual-server-route-error-pages/standard/virtual-server-updated.yaml
new file mode 100644
index 0000000000..d3660bbd73
--- /dev/null
+++ b/tests/data/virtual-server-route-error-pages/standard/virtual-server-updated.yaml
@@ -0,0 +1,16 @@
+apiVersion: k8s.nginx.org/v1
+kind: VirtualServer
+metadata:
+  name: virtual-server-route
+spec:
+  host: virtual-server-route.example.com
+  routes:
+  - path: "/backends"
+    route: backends
+    errorPages:
+      - codes: [502]
+        return:
+          code: 402
+          body: Hello World!
+  - path: "/backend2"
+    route: backend2-namespace/backend2
\ No newline at end of file
diff --git a/tests/data/virtual-server-route-error-pages/standard/virtual-server.yaml b/tests/data/virtual-server-route-error-pages/standard/virtual-server.yaml
new file mode 100644
index 0000000000..179878752a
--- /dev/null
+++ b/tests/data/virtual-server-route-error-pages/standard/virtual-server.yaml
@@ -0,0 +1,11 @@
+apiVersion: k8s.nginx.org/v1
+kind: VirtualServer
+metadata:
+  name: virtual-server-route
+spec:
+  host: virtual-server-route.example.com
+  routes:
+  - path: "/backends"
+    route: backends # implicit namespace
+  - path: "/backend2"
+    route: backend2-namespace/backend2
\ No newline at end of file
diff --git a/tests/suite/test_v_s_route_error_pages.py b/tests/suite/test_v_s_route_error_pages.py
new file mode 100644
index 0000000000..b67e45a08e
--- /dev/null
+++ b/tests/suite/test_v_s_route_error_pages.py
@@ -0,0 +1,132 @@
+import requests
+import pytest
+import json
+
+from settings import TEST_DATA
+from suite.custom_assertions import wait_and_assert_status_code, \
+    assert_event_starts_with_text_and_contains_errors
+from suite.custom_resources_utils import get_vs_nginx_template_conf, patch_v_s_route_from_yaml, \
+    patch_virtual_server_from_yaml
+from suite.resources_utils import get_first_pod_name, get_events, wait_before_test
+
+
+@pytest.mark.vsr
+@pytest.mark.parametrize('crd_ingress_controller, v_s_route_setup',
+                         [({"type": "complete", "extra_args": [f"-enable-custom-resources"]},
+                           {"example": "virtual-server-route-error-pages"})],
+                         indirect=True)
+class TestVSRErrorPages:
+    def test_redirect_strategy(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller,
+                               v_s_route_setup):
+        req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}"
+        wait_and_assert_status_code(307, f"{req_url}{v_s_route_setup.route_m.paths[0]}",
+                                    v_s_route_setup.vs_host, allow_redirects=False)
+        resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}",
+                            headers={"host": v_s_route_setup.vs_host}, allow_redirects=False)
+        assert f'http://{v_s_route_setup.vs_host}/error.html' in resp.next.url
+
+    def test_return_strategy(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller,
+                             v_s_route_setup):
+        req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}"
+        wait_and_assert_status_code(207, f"{req_url}{v_s_route_setup.route_m.paths[1]}", v_s_route_setup.vs_host)
+        resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}",
+                            headers={"host": v_s_route_setup.vs_host})
+        resp_content = json.loads(resp.content)
+        assert resp_content['status'] == '502' \
+            and resp_content['message'] == 'Forbidden' \
+            and resp.headers.get('x-debug-original-status') == '502'
+
+    def test_virtual_server_after_update(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller,
+                                         v_s_route_setup):
+        req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}"
+        patch_v_s_route_from_yaml(kube_apis.custom_objects,
+                                  v_s_route_setup.route_m.name,
+                                  f"{TEST_DATA}/virtual-server-route-error-pages/route-multiple-updated.yaml",
+                                  v_s_route_setup.route_m.namespace)
+        wait_and_assert_status_code(301, f"{req_url}{v_s_route_setup.route_m.paths[0]}",
+                                    v_s_route_setup.vs_host, allow_redirects=False)
+        resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}",
+                            headers={"host": v_s_route_setup.vs_host, "x-forwarded-proto": "http"},
+                            allow_redirects=False)
+        assert f'http://{v_s_route_setup.vs_host}/error_http.html' in resp.next.url
+
+        wait_and_assert_status_code(502, f"{req_url}{v_s_route_setup.route_m.paths[1]}",
+                                    v_s_route_setup.vs_host, allow_redirects=False)
+        resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}",
+                            headers={"host": v_s_route_setup.vs_host})
+        resp_content = resp.content.decode('utf-8')
+        assert resp_content == 'Hello World!\n'
+
+    def test_validation_event_flow(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller,
+                                   v_s_route_setup):
+        invalid_fields_m = [
+            "spec.subroutes[0].errorPages[0].redirect.url: Invalid value",
+            "spec.subroutes[0].errorPages[0].redirect.code: Invalid value: 101",
+            "spec.subroutes[1].errorPages[0].return.body: Invalid value: \"status\"",
+            "spec.subroutes[1].errorPages[0].return.code: Invalid value: 100",
+            "spec.subroutes[1].errorPages[0].return.headers[0].value: Invalid value: \"schema\""
+        ]
+        invalid_fields_s = [
+            "spec.subroutes[0].errorPages[0].redirect.url: Required value: must specify a url"
+        ]
+        text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}"
+        text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}"
+        vsr_s_event_text = f"VirtualServerRoute {text_s} is invalid and was rejected: "
+        vsr_m_event_text = f"VirtualServerRoute {text_m} is invalid and was rejected: "
+        patch_v_s_route_from_yaml(kube_apis.custom_objects,
+                                  v_s_route_setup.route_s.name,
+                                  f"{TEST_DATA}/virtual-server-route-error-pages/route-single-invalid.yaml",
+                                  v_s_route_setup.route_s.namespace)
+        patch_v_s_route_from_yaml(kube_apis.custom_objects,
+                                  v_s_route_setup.route_m.name,
+                                  f"{TEST_DATA}/virtual-server-route-error-pages/route-multiple-invalid.yaml",
+                                  v_s_route_setup.route_m.namespace)
+        wait_before_test(2)
+        ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace)
+        config = get_vs_nginx_template_conf(kube_apis.v1,
+                                            v_s_route_setup.namespace,
+                                            v_s_route_setup.vs_name,
+                                            ic_pod_name,
+                                            ingress_controller_prerequisites.namespace)
+        vsr_s_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace)
+        vsr_m_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace)
+
+        assert_event_starts_with_text_and_contains_errors(vsr_s_event_text, vsr_s_events, invalid_fields_s)
+        assert_event_starts_with_text_and_contains_errors(vsr_m_event_text, vsr_m_events, invalid_fields_m)
+        assert "upstream" not in config
+
+    @pytest.mark.parametrize('v_s_r_data', [
+        {"src": "route-multiple-splits.yaml", "expected_code": 308},
+        {"src": "route-multiple-matches.yaml", "expected_code": 307}
+    ])
+    def test_splits_and_matches(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller,
+                                v_s_route_setup, v_s_r_data):
+        req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}"
+        patch_v_s_route_from_yaml(kube_apis.custom_objects,
+                                  v_s_route_setup.route_m.name,
+                                  f"{TEST_DATA}/virtual-server-route-error-pages/{v_s_r_data['src']}",
+                                  v_s_route_setup.route_m.namespace)
+        wait_and_assert_status_code(v_s_r_data["expected_code"], f"{req_url}{v_s_route_setup.route_m.paths[0]}",
+                                    v_s_route_setup.vs_host, allow_redirects=False)
+        resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}",
+                            headers={"host": v_s_route_setup.vs_host}, allow_redirects=False)
+        assert f'http://{v_s_route_setup.vs_host}/error.html' in resp.next.url
+
+    def test_vsr_overrides_vs(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller,
+                              v_s_route_setup):
+        req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}"
+        vs_src = f"{TEST_DATA}/virtual-server-route-error-pages/standard/virtual-server-updated.yaml"
+        patch_virtual_server_from_yaml(kube_apis.custom_objects,
+                                       v_s_route_setup.vs_name,
+                                       vs_src,
+                                       v_s_route_setup.namespace)
+        patch_v_s_route_from_yaml(kube_apis.custom_objects,
+                                  v_s_route_setup.route_m.name,
+                                  f"{TEST_DATA}/virtual-server-route-error-pages/route-multiple.yaml",
+                                  v_s_route_setup.route_m.namespace)
+        wait_and_assert_status_code(307, f"{req_url}{v_s_route_setup.route_m.paths[0]}",
+                                    v_s_route_setup.vs_host, allow_redirects=False)
+        resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}",
+                            headers={"host": v_s_route_setup.vs_host}, allow_redirects=False)
+        assert f'http://{v_s_route_setup.vs_host}/error.html' in resp.next.url
+
diff --git a/tests/suite/test_virtual_server_error_pages.py b/tests/suite/test_virtual_server_error_pages.py
new file mode 100644
index 0000000000..4a753a5f62
--- /dev/null
+++ b/tests/suite/test_virtual_server_error_pages.py
@@ -0,0 +1,87 @@
+import pytest
+import json
+import requests
+
+from suite.custom_assertions import wait_and_assert_status_code, assert_vs_conf_not_exists, \
+    assert_event_starts_with_text_and_contains_errors
+from settings import TEST_DATA
+from suite.custom_resources_utils import patch_virtual_server_from_yaml
+from suite.resources_utils import wait_before_test, get_first_pod_name, get_events
+
+
+@pytest.mark.vs
+@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup',
+                         [({"type": "complete", "extra_args": [f"-enable-custom-resources"]},
+                           {"example": "virtual-server-error-pages", "app_type": None})],
+                         indirect=True)
+class TestVSErrorPages:
+    def test_redirect_strategy(self, kube_apis, crd_ingress_controller, virtual_server_setup):
+        wait_and_assert_status_code(307, virtual_server_setup.backend_1_url,
+                                    virtual_server_setup.vs_host, allow_redirects=False)
+        resp = requests.get(virtual_server_setup.backend_1_url,
+                            headers={"host": virtual_server_setup.vs_host}, allow_redirects=False)
+        assert f'http://{virtual_server_setup.vs_host}/error.html' in resp.next.url
+
+    def test_return_strategy(self, kube_apis, crd_ingress_controller, virtual_server_setup):
+        wait_and_assert_status_code(207, virtual_server_setup.backend_2_url, virtual_server_setup.vs_host)
+        resp = requests.get(virtual_server_setup.backend_2_url,
+                            headers={"host": virtual_server_setup.vs_host})
+        resp_content = json.loads(resp.content)
+        assert resp_content['status'] == '502' \
+            and resp_content['message'] == 'Forbidden' \
+            and resp.headers.get('x-debug-original-status') == '502'
+
+    def test_virtual_server_after_update(self, kube_apis, crd_ingress_controller, virtual_server_setup):
+        patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name,
+                                       f"{TEST_DATA}/virtual-server-error-pages/virtual-server-updated.yaml",
+                                       virtual_server_setup.namespace)
+        wait_and_assert_status_code(301, virtual_server_setup.backend_1_url,
+                                    virtual_server_setup.vs_host, allow_redirects=False)
+        resp = requests.get(virtual_server_setup.backend_1_url,
+                            headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"},
+                            allow_redirects=False)
+        assert f'http://{virtual_server_setup.vs_host}/error_http.html' in resp.next.url
+
+        wait_and_assert_status_code(502, virtual_server_setup.backend_2_url, virtual_server_setup.vs_host)
+        resp = requests.get(virtual_server_setup.backend_2_url,
+                            headers={"host": virtual_server_setup.vs_host})
+        resp_content = resp.content.decode('utf-8')
+        assert resp_content == 'Hello World!\n'
+
+    def test_validation_event_flow(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller,
+                                   virtual_server_setup):
+        invalid_fields = [
+            "spec.routes[0].errorPages[0].redirect.url: Invalid value",
+            "spec.routes[0].errorPages[0].redirect.code: Invalid value: 101",
+            "spec.routes[1].errorPages[0].return.body: Invalid value: \"status\"",
+            "spec.routes[1].errorPages[0].return.code: Invalid value: 100",
+            "spec.routes[1].errorPages[0].return.headers[0].value: Invalid value: \"schema\""
+        ]
+        text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}"
+        vs_event_text = f"VirtualServer {text} is invalid and was rejected: "
+        vs_file = f"{TEST_DATA}/virtual-server-error-pages/virtual-server-invalid.yaml"
+        patch_virtual_server_from_yaml(kube_apis.custom_objects,
+                                       virtual_server_setup.vs_name,
+                                       vs_file,
+                                       virtual_server_setup.namespace)
+        wait_before_test(2)
+        ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace)
+        vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace)
+
+        assert_event_starts_with_text_and_contains_errors(vs_event_text, vs_events, invalid_fields)
+        assert_vs_conf_not_exists(kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace,
+                                  virtual_server_setup)
+
+    @pytest.mark.parametrize('v_s_data', [
+        {"src": "virtual-server-splits.yaml", "expected_code": 308},
+        {"src": "virtual-server-matches.yaml", "expected_code": 307}
+    ])
+    def test_splits_and_matches(self, kube_apis, crd_ingress_controller, virtual_server_setup, v_s_data):
+        patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name,
+                                       f"{TEST_DATA}/virtual-server-error-pages/{v_s_data['src']}",
+                                       virtual_server_setup.namespace)
+        wait_and_assert_status_code(v_s_data['expected_code'], virtual_server_setup.backend_1_url,
+                                    virtual_server_setup.vs_host, allow_redirects=False)
+        resp = requests.get(virtual_server_setup.backend_1_url,
+                            headers={"host": virtual_server_setup.vs_host}, allow_redirects=False)
+        assert f'http://{virtual_server_setup.vs_host}/error.html' in resp.next.url