Skip to content

Fix quote reply becoming invalid after source message edit#30453

Open
overpathz wants to merge 1 commit intotelegramdesktop:devfrom
overpathz:dev
Open

Fix quote reply becoming invalid after source message edit#30453
overpathz wants to merge 1 commit intotelegramdesktop:devfrom
overpathz:dev

Conversation

@overpathz
Copy link
Copy Markdown

@overpathz overpathz commented Mar 16, 2026

Problem

When user A sends a message, user B selects part of it and chooses
Quote & Reply, then user A edits that message — user B's send gets
stuck with QUOTE_TEXT_INVALID error from the server.

Root cause

The quote_text stored in reply state was never invalidated when the
source message was edited. The client sent a stale quote to the
server which no longer matched the current message text.

Fix

Subscribe to message edit updates for the reply target. On edit,
re-validate the stored quote against the current message text.
If valid but entities changed — update them. If the quoted fragment
no longer exists — clear the quote and fall back to plain reply.

Steps to reproduce

  1. User A sends "hello world"
  2. User B selects "hello" → Quote & Reply
  3. User A edits the message (removes "hello")
  4. User B tries to send → stuck in a sending loop and get error on UI from the server? (QUOTE_TEXT_INVALID)

Video repro

Screen.Recording.2026-03-16.at.21.57.47.mov

Business Value / UX Impact

Prevents a frustrating "dead end" UX where user messages get permanently stuck in a sending state. By gracefully falling back to a standard reply, this fix ensures uninterrupted communication flow and makes the app feel more reliable during active, real-time chats.

Repro details

User A -- iOS, IPhone 14 Pro
tg version: 12.5.2

User B -- MacBook Pro, Apple M1 Pro, 2021. Tg version: 6.6.3 Beta

When a user selects text and uses Quote & Reply, then the original
message is edited; the stored quote_text could become stale.
Sending would fail with QUOTE_TEXT_INVALID from the server.

Now on message edit the quote is re-validated: if the quoted
fragment still exists at the same offset, entities are refreshed;
if the fragment no longer exists, the quote is cleared and a
plain reply is kept instead.
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 16, 2026

CLA assistant check
All committers have signed the CLA.

Comment on lines +417 to +418
const auto editId = _editMsgId.current();
if (editId) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const auto editId = _editMsgId.current();
if (editId) {
if (const auto editId = _editMsgId.current()) {

[[nodiscard]] bool ExtractCurrentQuote(
not_null<HistoryItem*> item,
const FullReplyTo &reply,
TextWithEntities &result) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We try to avoid doing that.
If you need to get two results from a function (in this case, bool and TextWithEntities), define a structure with two fields at the top that the function will return.

auto updated = reply;
updated.quote = TextWithEntities();
updated.quoteOffset = 0;
_replyTo = updated;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the point of all this moving from one empty place to another?

@23rd
Copy link
Copy Markdown
Collaborator

23rd commented Mar 25, 2026

I guess you did not test your changes?
I won't either.

@overpathz
Copy link
Copy Markdown
Author

@23rd
Thanks for review!
I will check it and address asap

Related to testing - yep, I didn't test it.
Btw, do you know someone who can help me to setup locally TG and try to reproduce that stuff..?

Copy link
Copy Markdown

@maxamedbarkhad580-hash maxamedbarkhad580-hash left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gh pr checkout 30453

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.

4 participants