Skip to content

✨ discard oversized non-file paste items to prevent huge database rows - #4699

Merged
guiyanakuang merged 4 commits into
mainfrom
feat/issue-4698-discard-oversized-non-file-paste
Jul 31, 2026
Merged

✨ discard oversized non-file paste items to prevent huge database rows#4699
guiyanakuang merged 4 commits into
mainfrom
feat/issue-4698-discard-oversized-non-file-paste

Conversation

@guiyanakuang

@guiyanakuang guiyanakuang commented Jul 31, 2026

Copy link
Copy Markdown
Member

Closes #4698

Summary

Adds a write-side defense against oversized paste rows (root cause of a mobile production crash: single rows >10MB hitting Android's CursorWindow limit). The limit applies only to non-file carrier types — text / HTML / RTF / URL / color; files and images are exempt and remain governed by maxSyncFileSize.

The limit is always on — there is no enable/disable toggle. It is a robustness defense, not a preference; the escape hatch for users who intentionally copy huge text is raising the MB value. Note the receive-side check always runs with the receiving device's own config, so one device raising its limit never weakens another device's protection.

Changes

Config (shared commonMain + desktop/e2e/cli implementations)

  • maxNonFilePasteSize: Long (MB, default 8), styled after maxSyncFileSize. Legacy configs without the field deserialize to the default. No enable flag — the limit cannot be turned off.

Local write path (DiscardOversizedNonFilePlugin, commonMain)

  • Registered in the process pipeline right after RemoveInvalidPlugin.
  • Oversized non-file items are filtered out silently (flavor degradation, log only). If every item is discarded, one warning notification is shown (non_file_paste_discarded_too_large); the resulting empty list makes PasteReleaseService mark-delete the row via the existing path.
  • COLOR is included so the "non-file" semantics are exact (it is 8 bytes and can never exceed the limit).

Remote receive path (PasteReleaseService.releaseRemotePasteData)

  • Remote pastes bypass the plugin pipeline, so a dedicated pre-persist check skips the whole paste when any non-file item is oversized, and notifies with the source device name (remote_non_file_paste_discarded_too_large).
  • Whole-paste skip is deliberate: the remote PasteData's hash/pasteType/searchContent are already assembled, and flavor degradation would break the hash-content consistency that same-hash dedup relies on. The sender keeps the full data, so nothing is lost.
  • releaseRemotePasteDataForPush (file-only path) is intentionally unchanged.

Settings UI

  • A single MB counter (min 1) in pasteboard settings, right below max_back_up_file_size — the limit governs local recording, so it lives with the other recording controls rather than in network settings. The item subtitle spells out the affected types and the file/image exemption.

i18n

  • 4 keys (max_non_file_paste_size, max_non_file_paste_size_desc, non_file_paste_discarded_too_large, remote_non_file_paste_discarded_too_large) across all 10 language files.

Tests

  • DiscardOversizedNonFilePluginTest: all-oversized → empty + notification; partial → silent degradation; raised limit retains items; file/image exempt; empty input; exact-at-limit retained.
  • PasteReleaseServiceRemoteDiscardTest: oversized remote paste skipped with notification; within-limit and raised-limit paths release normally.
  • Config default/copy/legacy-deserialization coverage in DesktopAppConfigTest.
  • Full app:desktopTest suite passes; e2e and cli compile.

Notes

  • No sender-side skip and no spill-to-file for large text (future work).
  • PasteItem.size is pre-maintained and not recomputed.
  • Mobile repos will follow up (config implementation, DI registration, settings UI) after this lands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Discard oversized non-file paste items to prevent huge database rows

1 participant