Skip to content

Notes: Don't lose a reply to a note deleted in another session - #85202

Open
yyppsk wants to merge 2 commits into
WordPress:trunkfrom
yyppsk:fix/notes-reply-to-deleted-note
Open

yyppsk wants to merge 2 commits into
WordPress:trunkfrom
yyppsk:fix/notes-reply-to-deleted-note

Conversation

@yyppsk

@yyppsk yyppsk commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

What?

Closes #80678

Stops a note reply, or a change to a note, from being saved after another session has deleted that note. The editor now shows an error and keeps the typed text, instead of reporting success and losing the reply.

Why?

Two editor sessions can disagree about whether a note still exists. When session A submits a reply after session B deleted the note, the request succeeds and the editor announces "Reply added.", but the reply is stored under the trashed note and no longer appears anywhere in the editor.

The same race affects Reopen & Reply on a resolved note. Reopening sets the note's status, which moves the deleted note out of the trash without the replies that were trashed along with it, so the thread comes back with only the new reply. Resolving or editing a deleted note is accepted the same way.

How?

Both changes are in the WordPress 7.2 compat comments controller, Gutenberg_REST_Comment_Controller_7_2:

  • create_item() rejects a note reply whose parent is trashed, marked as spam, or permanently deleted, with 400 rest_comment_invalid_parent. Reactions are already validated this way.
  • A new update_item() override rejects any change to a trashed or spam note other than restoring it (status: untrash or unspam), with 400 rest_comment_invalid_status. The editor's Undo sends untrash, so it keeps working.

The editor already shows REST error messages in a snackbar, and the note form only clears after a successful save, so no JavaScript changes are needed.

Core's WP_REST_Comments_Controller has the same gap, so this needs a Core backport. Marked as WIP until the Trac ticket, the wordpress-develop PR and the backport-changelog entry are added.

Testing Instructions

Reply to a deleted note

  1. Sign the same administrator account into two browser sessions, for example a normal window (A) and a private window (B).
  2. In A, create a post, add a Paragraph, add a note to it, and save the draft.
  3. Open the same post in B and open All notes.
  4. In A, select the note and type a reply, but don't submit it.
  5. In B, choose the note's Actions → Delete, confirm, and wait for "Note deleted.".
  6. In A, without reloading, click Reply.

Reopen & Reply on a deleted note

  1. Follow steps 1–3 above, then in A resolve the note.
  2. In A, type a reply on the resolved note. The button reads Reopen & Reply. Don't submit it.
  3. In B, delete the note.
  4. In A, click Reopen & Reply.
    • Before: the note comes back as open with only the new reply. Its earlier replies stay in the trash.
    • After: "This note was deleted, so it could not be updated." The note stays deleted and the reply text stays in the form.

Undo still restores a note

  1. Delete a note that has a reply.
  2. Click Undo in the "Note deleted." snackbar. The note and its reply come back.

Automated

npm run test:unit:php:base -- --filter WP_Test_REST_Comments_Controller_Gutenberg

Testing Instructions for Keyboard

There are no UI changes. To check the error with the keyboard, follow the steps above, Tab to the reply field and type the reply, then Tab to Reply (or Reopen & Reply) and press Enter after the note is deleted in the other session. The error appears in a snackbar like other notices, and the reply text stays in the form.

Screenshots or screencast

Before After

Use of AI Tools

This PR was authored with Claude Code (Claude Opus 5.5). It reproduced both races in two browser sessions on trunk, wrote the fix and the PHPUnit tests, and drafted this description.

When a note is deleted in one session while a reply to it is being
written in another, submitting the reply succeeded and announced
"Reply added.", but the reply was stored under the trashed note and
was no longer shown anywhere in the editor.

Reject a note reply whose parent is trashed, marked as spam or
permanently deleted, as reactions already are, so the editor shows
an error instead of losing the reply.

Fixes WordPress#80678.
When a resolved note was deleted in one session, "Reopen & Reply" in
another session brought it back: reopening sets the note's status,
which moved it out of the trash without the replies trashed along
with it, and the new reply was then stored under it. Resolving or
editing a deleted note was accepted the same way.

Reject any change to a deleted note other than restoring it, so the
editor shows an error instead. Undo still restores the note and its
replies.

See WordPress#80678.
@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

🤖 PR meta 🤖

Preview in WordPress Playground

🎉 Props

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: yyppsk <pranjalpratapsingh@git.wordpress.org>
Co-authored-by: prachigarg19 <prachigarg19@git.wordpress.org>
Co-authored-by: mcliwanow <mcliwanow@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Updated as activity occurs, without notifying anyone named here. Add the props-bot label to refresh.

🏷️ Labels

This pull request needs exactly one label indicating its type, and has 0.

  • Required: any label starting with [Type].
  • Found: none.

Read more about Type labels in Gutenberg. If you cannot add labels yourself, a reviewer can do it for you.

This branch has not been deployed

No deployments
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.

Notes: A reply is stored under a deleted parent and becomes unavailable in the editor

1 participant