diff --git a/libraries/overleaf-editor-core/lib/operation/text_operation.js b/libraries/overleaf-editor-core/lib/operation/text_operation.js index e153f0c3ec..76a738c428 100644 --- a/libraries/overleaf-editor-core/lib/operation/text_operation.js +++ b/libraries/overleaf-editor-core/lib/operation/text_operation.js @@ -45,9 +45,13 @@ class TextOperation extends EditOperation { /** * Length of the longest file that we'll attempt to edit, in characters. * + * Backend OT/history processing limit. Incoming uploads/edits are separately + * capped at 2MB via `max_doc_length`; this higher ceiling lets legacy updates + * with larger OT results flow through history instead of throwing TooLongError. + * * @type {number} */ - static MAX_STRING_LENGTH = 2 * Math.pow(1024, 2) + static MAX_STRING_LENGTH = 3 * Math.pow(1024, 2) static UnprocessableError = UnprocessableError static ApplyError = ApplyError static InvalidInsertionError = InvalidInsertionError diff --git a/services/web/frontend/js/features/source-editor/extensions/realtime.ts b/services/web/frontend/js/features/source-editor/extensions/realtime.ts index 99d60262c5..4932c70aab 100644 --- a/services/web/frontend/js/features/source-editor/extensions/realtime.ts +++ b/services/web/frontend/js/features/source-editor/extensions/realtime.ts @@ -332,6 +332,11 @@ class HistoryOTAdapter { handleUpdateFromCM(transactions: readonly Transaction[]) { for (const transaction of transactions) { + // TODO: unlike the sharejs adapter above, this only checks visible + // length. When history-ot is enabled, add the retained tracked-deletes + // length here too (as #20052 did for sharejs) — otherwise total stored + // content (visible + tracked deletes) can exceed the backend cap + // (TextOperation.MAX_STRING_LENGTH) and fail with a 422. if ( this.maxDocLength && transaction.changes.newLength >= this.maxDocLength