Reproduction steps that start where the reader is
Reproduction steps are the one thing everybody knows to ask for and the one thing most often supplied in a form that does not work.
The failure is nearly always the same. The steps begin halfway through, from a state the reporter had spent an hour building up without noticing, because to them it was not a state, it was just Tuesday.
1. Open the report
2. Change the date range
3. Click export
4. File is wrong
Every line of that is true and none of it is followable. Which report. Whose account. What date range, from what to what. The reporter can follow it perfectly, which is precisely why it got filed.
Rule one: start from a state the reader can reach
The first step should be something a stranger can do. A fresh login, a named test account, a specific record with an identifier, a URL. If step one is "open the report you were working on", the issue is reproducible by exactly one person in the world.
The test is mechanical: could somebody who has never seen your setup execute step one? If not, there is a step missing above it.
Rule two: name the data, not the shape of the data
"A large report" is not a fact. "The All Activity report for the last 90 days, which is about 4,300 rows" is a fact, and in that particular example the number of rows turned out to be the entire bug, because the limit was at 1,000.
Reporters generalise out of politeness. They assume the specifics are noise and that you want the pattern. Almost always the reverse is true: one concrete case with real values beats three descriptions of the category.
Rule three: separate what you did from what you saw
Steps that mix action and outcome hide the moment things went wrong.
1. Log in as qa@example.com
2. Reports → All Activity
3. Set range to 1 May to 29 July (4,300 rows shown in the table header)
4. Click Export CSV
Expected: 4,300 rows in the file.
Saw: 1,000 rows, no error, no warning. Same in Safari and Chrome.
The list is now instructions. The outcome is stated once, at the end, where it does not interrupt the sequence. And the row counts in steps three and the outcome are what turn this from a report into a diagnosis.
Rule four: say how many times you tried
"It happens sometimes" and "it happens every time" are different bugs, and the difference decides whether anyone can chase it. One attempt is fine to report, as long as it says so. What is not fine is leaving the reader to guess, because they will assume it is reproducible, fail to reproduce it, and close the ticket.
Three attempts and a note is the cheapest thing a reporter can do to improve a ticket, and almost nobody does it, because nobody has ever asked them to.
What to do when there are no steps
Sometimes there genuinely are none. It happened once, in production, three weeks ago, and nobody can make it happen again. That ticket is still worth having, but it needs different things:
- A timestamp. Even approximate. It turns an unreproducible report into a log search, which is often better than reproduction anyway.
- An identifier. The user, the account, the record, the request ID if one was shown.
- What was different. First time using the feature, unusually large file, just after a deploy, on a train with bad signal.
Those three turn "cannot reproduce" into "can investigate", which is a completely different outcome for a ticket that would otherwise be closed unread.
Why this keeps happening
None of this is difficult, and every developer reading it already knows it. It keeps happening because the person best placed to write good steps is the one least able to know what "good" means here, and the gap is only visible from the other side.
Which makes it a question problem rather than a training problem. "What would I have to do, from a fresh login, to see what you saw?" gets a usable answer from almost anyone, on the first ask, and does not require the reporter to have read anything about writing bug reports.
WhatProblem asks these questions for you
It reads new GitHub issues and asks what is missing, in the issue thread, before anyone on your team has to.
Install from GitHub Marketplace