How to Write a Review Comment That Unsticks the Author
Open any code review thread on GitHub and count the comments that get a reply. Most of them do not, and the reason is rarely that the author disagrees. The comment sits there, the author reads it, and then the author does what anyone does when handed an instruction with no handle on it: nothing. The review comment was not wrong. It was just impossible to act on.
This is a craft problem, and it has a craft solution. A comment that unsticks an author gives them a place to start, a shape for the fix, and a way to know when they are done. Those three things are almost never present in the comments that stall.
The comment that names a feeling and nothing else
The most common stuck comment is some version of "this feels off." It is honest. It is also useless to the person receiving it, because the feeling lives in the reviewer's head and the author has no access to it. The author rereads the function, finds nothing, and either guesses or waits.
Guessing is worse than waiting. A guess based on a vague feeling produces a rewrite that fixes the wrong thing, and now two people are confused.
A comment that unsticks names the observable. Something in the code, the test, the output, or the behavior that the reviewer can point at. "The retry loop swallows the exception on line 84, so the caller never learns the upload failed." That is a different animal. The author can see the line, agree or disagree, and move.
Pointing at the line without explaining the consequence
Naming the line is half the work. The other half is the consequence. A reviewer who writes "this naming is confusing" has pointed at something but not said why it matters, and the author is left to guess whether the fix is a rename, a comment, or a restructure.
The consequence is the sentence that converts a complaint into a task. Confusing naming costs the next reader a minute of parsing. A swallowed exception costs a support ticket. A missing test costs a regression in three months. Say which one, and the author knows how much room the fix deserves.
This is also where reviewers accidentally overreach. "This naming is confusing and will cause bugs" is a consequence stated as a certainty that the reviewer cannot actually support. "The next reader will have to trace two files to learn what this does" is a consequence the reviewer can defend, because they just did it.
The difference between a diagnosis and a prescription
Reviewers who want to be helpful tend to jump to the fix. "Rename this to pendingUploads." "Extract this into a helper." "Use a map here." The prescription feels efficient, and sometimes it is exactly right. More often it hands the author a decision they did not get to make, and the author either complies without understanding or pushes back and the thread becomes a debate about taste.
A diagnosis leaves the author the choice of treatment. "This function does three things: validates, uploads, and logs. Each one fails differently, and right now a validation failure and a network failure produce the same error message." That comment tells the author what the reviewer sees, and the author can decide whether to split the function, differentiate the errors, or argue that the current shape is intentional.
Prescriptions are not banned. A reviewer who has a strong opinion should say so, and a good author will take it seriously. The prescription just needs to arrive after the diagnosis, so the author can follow the reasoning rather than reverse-engineer it.
Scoping the fix with a done condition
Here is the part that separates a comment that unsticks from a comment that merely informs: the done condition. The author needs to know what state the code should be in when the comment is resolved, and reviewers almost never say.
"Add error handling" has no done condition. Does it mean a try/catch around the upload? A retry with backoff? A user-facing message? A log line? The author will pick one, and there is a good chance the reviewer meant another, and now the thread has a second round.
"When the upload fails, the caller should get a typed error with the original exception attached, so the UI can show a retry button. A try/catch at the call site is enough for now." That comment has a done condition. The author can finish it, mark it resolved, and the reviewer can verify in one pass.
The done condition is also a scoping tool. It tells the author how far to go, which matters enormously when the comment touches a file the author did not write and does not want to refactor at 4pm on a Friday.
Asking a question instead of issuing a verdict
Some comments are better as questions, and the trick is knowing which ones. A question signals that the reviewer might be missing context, which keeps the author from getting defensive. A verdict signals that the reviewer has decided, which is fine when they have.
"What happens if the token expires mid-request?" is a question that unsticks, because it points at a scenario and invites the author to either explain the handling or admit there is none. "This does not handle token expiry" is a verdict, and it is stronger when the reviewer is certain, weaker when they are not.
The question form has a second benefit. It gives the author a chance to teach the reviewer something, and a review thread where the author gets to explain a design decision is a thread the author will engage with. Engagement is the whole point. A comment that unsticks is a comment the author wants to answer.
Separating blockers from preferences
A review thread stalls fastest when the author cannot tell which comments must be resolved before merge and which are suggestions. Every comment looks the same in the interface, so the author treats them all as blockers, gets overwhelmed, and the thread sits.
The fix is a label in the comment itself. "Blocking: the error is swallowed and the caller cannot tell." "Non-blocking: I would name this differently, take it or leave it." Two extra words and the author knows what to do first, what to do later, and what to ignore.
The label also protects the reviewer. A non-blocking preference stated as a preference is a preference the author can decline without a fight. A non-blocking preference stated as a verdict turns into a negotiation about code style that neither person wanted to have.
The review comment that arrives with a diff
GitHub's suggestion feature lets a reviewer attach a proposed diff to a comment, and it is the single highest-leverage tool for unsticking an author. A suggested change removes the ambiguity of prose entirely. The author sees the exact lines, accepts or rejects with one click, and the thread closes.
Reviewers underuse it because writing a suggestion feels like doing the author's job. It is not. A suggestion is a starting point, and it is faster for the author to edit a concrete diff than to write a fix from a description. The suggestion also forces the reviewer to be specific, because a diff cannot be vague.
Use it for the small stuff: a rename, a reordered condition, a missing null check. Leave the structural comments as prose, because a diff that restructures a function is a diff that takes over the author's work.
When the comment should be a conversation, not a thread
Some comments should not be comments at all. A design disagreement that will take four rounds to resolve is a conversation, and putting it in a review thread guarantees that it stalls, because the author reads it between other tasks and the reviewer is asleep in another time zone.
The unsticking move is to say so. "This is a design question, can we talk for ten minutes tomorrow?" The comment is now a calendar item, and the author is no longer stuck on prose they cannot resolve in prose.
Reviewers resist this because it feels like escalation. It is the opposite. A ten-minute call resolves in a day what a thread resolves in a week, and the thread that remains is cleaner for it.
The comment the author can close in one pass
The test of an unsticking comment is simple: can the author read it once, make a change, and mark it resolved without asking a follow-up question? If yes, the comment did its job. If no, the comment needs another sentence.
That sentence is usually the done condition. Reviewers write the diagnosis and stop, because the diagnosis is the interesting part. The done condition is the boring part, and it is the part the author needs.
A reviewer who writes "the retry loop swallows the exception, so the caller never learns the upload failed, and the fix is a typed error at the call site with the original exception attached" has written a comment the author can close in one pass. The author reads it, opens the file, makes the change, marks it resolved, and moves to the next comment.
That is the whole craft. The comment is not a verdict on the author's work. It is a set of instructions specific enough to follow, scoped enough to finish, and honest enough that the author trusts the reviewer meant what they wrote. The threads that stall are the ones missing one of those three, and the reviewer who adds the missing piece is the reviewer authors want on their pull requests.

