diff --git a/client/src/components/StreamField/blocks/ListBlock.js b/client/src/components/StreamField/blocks/ListBlock.js
index 7d1e96fc89..dc2a566a5d 100644
--- a/client/src/components/StreamField/blocks/ListBlock.js
+++ b/client/src/components/StreamField/blocks/ListBlock.js
@@ -11,13 +11,6 @@ import { range } from '../../../utils/range';
 
 /* global $ */
 
-export class ListBlockValidationError {
-  constructor(blockErrors, nonBlockErrors) {
-    this.blockErrors = blockErrors;
-    this.nonBlockErrors = nonBlockErrors;
-  }
-}
-
 class ListChild extends BaseSequenceChild {
   /*
   wrapper for an item inside a ListBlock
diff --git a/client/src/components/StreamField/blocks/StreamBlock.js b/client/src/components/StreamField/blocks/StreamBlock.js
index 2f9795f3d7..e84bb0fd4d 100644
--- a/client/src/components/StreamField/blocks/StreamBlock.js
+++ b/client/src/components/StreamField/blocks/StreamBlock.js
@@ -21,13 +21,6 @@ import { hideTooltipOnEsc } from '../../../includes/initTooltips';
 
 /* global $ */
 
-export class StreamBlockValidationError {
-  constructor(nonBlockErrors, blockErrors) {
-    this.nonBlockErrors = nonBlockErrors;
-    this.blockErrors = blockErrors;
-  }
-}
-
 class StreamChild extends BaseSequenceChild {
   /*
   wrapper for a block inside a StreamBlock, handling StreamBlock-specific metadata
diff --git a/client/src/components/StreamField/blocks/StructBlock.js b/client/src/components/StreamField/blocks/StructBlock.js
index d01a80569b..778ead4716 100644
--- a/client/src/components/StreamField/blocks/StructBlock.js
+++ b/client/src/components/StreamField/blocks/StructBlock.js
@@ -3,13 +3,6 @@
 import { escapeHtml as h } from '../../../utils/text';
 import { hasOwn } from '../../../utils/hasOwn';
 
-export class StructBlockValidationError {
-  constructor(nonBlockErrors, blockErrors) {
-    this.nonBlockErrors = nonBlockErrors;
-    this.blockErrors = blockErrors;
-  }
-}
-
 export class StructBlock {
   constructor(blockDef, placeholder, prefix, initialState, initialError) {
     const state = initialState || {};
diff --git a/client/src/entrypoints/admin/telepath/blocks.js b/client/src/entrypoints/admin/telepath/blocks.js
index d19e71d0af..5d9951b66a 100644
--- a/client/src/entrypoints/admin/telepath/blocks.js
+++ b/client/src/entrypoints/admin/telepath/blocks.js
@@ -9,17 +9,14 @@ import {
 import {
   StructBlock,
   StructBlockDefinition,
-  StructBlockValidationError,
 } from '../../../components/StreamField/blocks/StructBlock';
 import {
   ListBlock,
   ListBlockDefinition,
-  ListBlockValidationError,
 } from '../../../components/StreamField/blocks/ListBlock';
 import {
   StreamBlock,
   StreamBlockDefinition,
-  StreamBlockValidationError,
 } from '../../../components/StreamField/blocks/StreamBlock';
 
 const wagtailStreamField = window.wagtailStreamField || {};
@@ -33,15 +30,12 @@ wagtailStreamField.blocks = {
 
   StructBlock,
   StructBlockDefinition,
-  StructBlockValidationError,
 
   ListBlock,
   ListBlockDefinition,
-  ListBlockValidationError,
 
   StreamBlock,
   StreamBlockDefinition,
-  StreamBlockValidationError,
 };
 
 function initBlockWidget(id) {
@@ -71,19 +65,7 @@ window.initBlockWidget = initBlockWidget;
 window.telepath.register('wagtail.blocks.FieldBlock', FieldBlockDefinition);
 window.telepath.register('wagtail.blocks.StaticBlock', StaticBlockDefinition);
 window.telepath.register('wagtail.blocks.StructBlock', StructBlockDefinition);
-window.telepath.register(
-  'wagtail.blocks.StructBlockValidationError',
-  StructBlockValidationError,
-);
 window.telepath.register('wagtail.blocks.ListBlock', ListBlockDefinition);
-window.telepath.register(
-  'wagtail.blocks.ListBlockValidationError',
-  ListBlockValidationError,
-);
 window.telepath.register('wagtail.blocks.StreamBlock', StreamBlockDefinition);
-window.telepath.register(
-  'wagtail.blocks.StreamBlockValidationError',
-  StreamBlockValidationError,
-);
 
 window.wagtailStreamField = wagtailStreamField;
diff --git a/client/src/entrypoints/contrib/typed_table_block/typed_table_block.js b/client/src/entrypoints/contrib/typed_table_block/typed_table_block.js
index a12ac7204e..5b55bc0d02 100644
--- a/client/src/entrypoints/contrib/typed_table_block/typed_table_block.js
+++ b/client/src/entrypoints/contrib/typed_table_block/typed_table_block.js
@@ -584,13 +584,3 @@ window.telepath.register(
   'wagtail.contrib.typed_table_block.blocks.TypedTableBlock',
   TypedTableBlockDefinition,
 );
-
-export class TypedTableBlockValidationError {
-  constructor(cellErrors) {
-    this.cellErrors = cellErrors;
-  }
-}
-window.telepath.register(
-  'wagtail.contrib.typed_table_block.TypedTableBlockValidationError',
-  TypedTableBlockValidationError,
-);
diff --git a/docs/releases/5.0.md b/docs/releases/5.0.md
index 920f6a9caf..8c1b567539 100644
--- a/docs/releases/5.0.md
+++ b/docs/releases/5.0.md
@@ -162,3 +162,8 @@ Stimulus [targets](https://stimulus.hotwired.dev/reference/targets) and [actions
 * `<button ... data-action="w-progress#activate focus->w-progress#activate" ...>` - any event can be used to trigger the in progress behaviour
 * `<button ... data-action="w-progress#activate:once" ...>` - only trigger the progress behaviour once
 * `<button ... data-action="readystatechange@document->w-progress#activate:once" data-w-progress-duration-value="5000" disabled ...>` - disabled on load (once JS starts) and becomes enabled after 5s duration
+
+
+### Client-side `BlockValidationError` classes removed
+
+The client-side handling of StreamField validation errors has been updated. The JavaScript classes `StreamBlockValidationError`, `ListBlockValidationError`, `StructBlockValidationError` and `TypedTableBlockValidationError` have been removed, and the corresponding Python classes can no longer be serialised using Telepath. Instead, the `setError` methods on client-side block objects now accept a plain JSON representation of the error, obtained from the `as_json_data` method on the Python class. Custom JavaScript code that works with these objects must be updated accordingly.
diff --git a/wagtail/blocks/list_block.py b/wagtail/blocks/list_block.py
index 71b02e2d08..96eba4a38d 100644
--- a/wagtail/blocks/list_block.py
+++ b/wagtail/blocks/list_block.py
@@ -47,30 +47,6 @@ class ListBlockValidationError(ValidationError):
         return result
 
 
-class ListBlockValidationErrorAdapter(Adapter):
-    js_constructor = "wagtail.blocks.ListBlockValidationError"
-
-    def js_args(self, error):
-        return [
-            [
-                elist.as_data() if elist is not None else elist
-                for elist in error.block_errors
-            ],
-            error.non_block_errors.as_data(),
-        ]
-
-    @cached_property
-    def media(self):
-        return forms.Media(
-            js=[
-                versioned_static("wagtailadmin/js/telepath/blocks.js"),
-            ]
-        )
-
-
-register(ListBlockValidationErrorAdapter(), ListBlockValidationError)
-
-
 class ListValue(MutableSequence):
     """
     The native data type used by ListBlock. Behaves as a list of values, but also provides
diff --git a/wagtail/blocks/stream_block.py b/wagtail/blocks/stream_block.py
index 3a42fae409..990b7c3a7f 100644
--- a/wagtail/blocks/stream_block.py
+++ b/wagtail/blocks/stream_block.py
@@ -54,30 +54,6 @@ class StreamBlockValidationError(ValidationError):
         return result
 
 
-class StreamBlockValidationErrorAdapter(Adapter):
-    js_constructor = "wagtail.blocks.StreamBlockValidationError"
-
-    def js_args(self, error):
-        return [
-            error.non_block_errors.as_data(),
-            {
-                block_id: child_errors.as_data()
-                for block_id, child_errors in error.block_errors.items()
-            },
-        ]
-
-    @cached_property
-    def media(self):
-        return forms.Media(
-            js=[
-                versioned_static("wagtailadmin/js/telepath/blocks.js"),
-            ]
-        )
-
-
-register(StreamBlockValidationErrorAdapter(), StreamBlockValidationError)
-
-
 class BaseStreamBlock(Block):
     def __init__(self, local_blocks=None, **kwargs):
         self._constructor_kwargs = kwargs
diff --git a/wagtail/blocks/struct_block.py b/wagtail/blocks/struct_block.py
index 595f94432b..50863daaec 100644
--- a/wagtail/blocks/struct_block.py
+++ b/wagtail/blocks/struct_block.py
@@ -47,37 +47,6 @@ class StructBlockValidationError(ValidationError):
         return result
 
 
-class StructBlockValidationErrorAdapter(Adapter):
-    js_constructor = "wagtail.blocks.StructBlockValidationError"
-
-    def js_args(self, error):
-        if error.non_block_errors:
-            non_block_errors = error.non_block_errors.as_data()
-        else:
-            non_block_errors = None
-
-        if error.block_errors:
-            block_errors = {
-                name: error_list.as_data()
-                for name, error_list in error.block_errors.items()
-            }
-        else:
-            block_errors = None
-
-        return [non_block_errors, block_errors]
-
-    @cached_property
-    def media(self):
-        return forms.Media(
-            js=[
-                versioned_static("wagtailadmin/js/telepath/blocks.js"),
-            ]
-        )
-
-
-register(StructBlockValidationErrorAdapter(), StructBlockValidationError)
-
-
 class StructValue(collections.OrderedDict):
     """A class that generates a StructBlock value from provided sub-blocks"""
 
diff --git a/wagtail/contrib/typed_table_block/blocks.py b/wagtail/contrib/typed_table_block/blocks.py
index b69b64c200..78041f71bc 100644
--- a/wagtail/contrib/typed_table_block/blocks.py
+++ b/wagtail/contrib/typed_table_block/blocks.py
@@ -43,35 +43,6 @@ class TypedTableBlockValidationError(ValidationError):
         return result
 
 
-class TypedTableBlockValidationErrorAdapter(Adapter):
-    js_constructor = "wagtail.contrib.typed_table_block.TypedTableBlockValidationError"
-
-    def js_args(self, error):
-        if error.cell_errors is None:
-            return [None]
-        else:
-            return [
-                {
-                    row_index: {
-                        col_index: cell_error
-                        for col_index, cell_error in row_errors.items()
-                    }
-                    for row_index, row_errors in error.cell_errors.items()
-                }
-            ]
-
-    @cached_property
-    def media(self):
-        return forms.Media(
-            js=[
-                versioned_static("typed_table_block/js/typed_table_block.js"),
-            ]
-        )
-
-
-register(TypedTableBlockValidationErrorAdapter(), TypedTableBlockValidationError)
-
-
 class TypedTable:
     template = "typed_table_block/typed_table_block.html"