diff --git a/.changeset/nasty-cougars-hear.md b/.changeset/nasty-cougars-hear.md
new file mode 100644
index 0000000000..3b1106af81
--- /dev/null
+++ b/.changeset/nasty-cougars-hear.md
@@ -0,0 +1,5 @@
+---
+"@udecode/plate-core": patch
+---
+
+Fixes #2230: infinite recursion when using plugin field `then`
diff --git a/packages/core/src/types/plugin/PlatePlugin.ts b/packages/core/src/types/plugin/PlatePlugin.ts
index 09534b6334..bf820c0209 100644
--- a/packages/core/src/types/plugin/PlatePlugin.ts
+++ b/packages/core/src/types/plugin/PlatePlugin.ts
@@ -187,6 +187,11 @@ export type PlatePlugin<
plugin: WithPlatePlugin
) => Partial> | void;
+ /**
+ * For internal use. Tracks if then has been replaced for recursive calls.
+ */
+ _thenReplaced?: number;
+
/**
* Hook called when the editor is initialized.
*/
diff --git a/packages/core/src/utils/plate/overridePluginsByKey.ts b/packages/core/src/utils/plate/overridePluginsByKey.ts
index 10acca5112..c1503c06d8 100644
--- a/packages/core/src/utils/plate/overridePluginsByKey.ts
+++ b/packages/core/src/utils/plate/overridePluginsByKey.ts
@@ -49,15 +49,23 @@ export const overridePluginsByKey = <
const { then } = plugin;
if (then) {
- // override plugin.then
- plugin.then = (editor, p) => {
- const pluginThen = { key: plugin.key, ...then(editor, p) };
-
- return defaultsDeep(
- overridePluginsByKey(pluginThen as any, overrideByKey),
- pluginThen
- );
- };
+ if(typeof plugin._thenReplaced === 'undefined') {
+ plugin._thenReplaced = 0;
+ }
+ // Limit the number of times that `then` can be replaced.
+ // otherwise we will accidentally create a stack overflow.
+ // There is probably a better solution for this.
+ if((plugin._thenReplaced as number) < 3) {
+ // override plugin.then
+ plugin.then = (editor, p) => {
+ const pluginThen = { key: plugin.key, ...then(editor, p) };
+ return defaultsDeep(
+ overridePluginsByKey(pluginThen as any, overrideByKey),
+ pluginThen
+ );
+ };
+ (plugin._thenReplaced as number)++;
+ }
} else if (overrideByKey[plugin.key]?.then) {
// TODO: recursvie
plugin.then = overrideByKey[plugin.key].then as any;