A client asks for a bulk edit screen in the admin panel. The request is clear, it is easy to estimate, and we could have it in front of them inside a week. Build it and they will use it, and six months later their Mondays will look exactly like they do today. The screen was never the thing that was wrong.
The question behind the question
The XY Problem got its name in support channels, where people have been running into it for decades. Someone turns up asking how to get the last three characters of a filename. Helpful people answer, because it is an easy question. Ten messages later it emerges that what they wanted was the file extension, which is a different question with a different answer, and the careful substring they were building would have been wrong for every .jpeg and every .tar.gz on the machine.
Y is the thing that actually hurts. X is what somebody decided would fix it. By the time the request reaches an engineer, X is usually all that is left of it. The reasoning that produced X happened in a meeting we were not in, often months earlier, and it has since hardened into a requirement with a name and a line in a budget.

Nothing about this looks like a mistake while it is happening. Each step is a reasonable person doing their job. The problem is that the reason travels badly and the request travels well, so after two or three hops all that is left is a well-formed ask that nobody can trace back to an incident.
Four shapes it takes
The feature ask. A specific screen, a specific button, sometimes a mockup. The real problem almost always sits upstream: data arrives in a state that requires the correction the screen would make faster. Build the screen and you have industrialized the cleanup, which means the mess is now affordable and will never be fixed.
The rebuild. “The system has to be replaced.” Sometimes true. Usually the pain is one bottleneck, one query, one integration that fails at month end, and a rewrite reproduces the bottleneck faithfully because nobody wrote down what it was. Two years later there is a new system with the old problem and a fresh set of bugs around it.
The integration. “Connect A to B.” The data in A is wrong, and everyone in the room knows it is wrong, and they have all quietly built a habit of correcting it by hand in B. Syncing it does not fix the data. It moves the wrongness somewhere more expensive and removes the human who was catching it.
The AI-shaped ask. “We want an assistant that handles this.” Occasionally right. Often the fix is a scheduled job and a validation rule that nobody is excited to fund, because it does not sound like the future. The assistant is easier to get approved, which is exactly why it is the request that reaches us.
Why X is so hard to give up
By the time we hear about X, the client has done real work on it. They noticed something was wrong, they thought about it, they picked an approach, they explained it to their colleagues, and they defended it well enough that it survived into a budget. That is a genuine achievement inside most organizations.
So when we ask why, it does not land as curiosity. It lands as a challenge to work that already passed review. Worse, the person in the room with us is frequently not the person with the problem. They are carrying somebody else’s pain second hand, which means they can defend the solution fluently and cannot describe the symptom at all.
It is not a client thing
Nothing in this is specific to consulting. The variable is the distance between the person with the problem and the person doing the work, not who is paying. Clients are simply the case where that distance is longest and has a contract stretched across it.
Shorten the distance and the same thing happens at smaller scale. A ticket arrives from another team asking for one more column in an export, and the reason is that somebody downstream reconciles two reports by hand every Thursday. An issue on one of our open source repos proposes a new config option, and three replies later it turns out the person was working around a default we could just change. Someone asks you for a regex when the file they are parsing has a delimiter.
We do it to each other inside our own backlog, and to our future selves. You write the ticket for the fix you had in mind rather than the behaviour that annoyed you, and four months later it gets built by someone who never learned what the behaviour was.
The distance is not a defect. It is what lets an organization work on more than one thing at a time. It only means the reason gets dropped in transit, every single time, and somebody has to go back for it.
And now the model agrees with you
This got harder in the last two years, for one specific reason: ask a language model about X and it gives you a better X.
It works inside the frame you hand it. Ask how to build the bulk edit screen and you will get a considered answer about the bulk edit screen, with a component breakdown, an argument for optimistic updates, and a section on edge cases. It is good work. It is also the same mistake the helpdesk made with the filename, performed at higher quality and much greater speed. The model very rarely stops to ask what happens if you never build the screen at all, because you did not ask that, and agreeing with your framing is the shape of a helpful answer.
The result is that clients now arrive with X already written up. It has headings. It has a rollout plan. Sometimes it has a working prototype, which is the strongest form of this, because a thing that exists is very hard to argue against. Their hunch went into the model and came back out as a document, and the confidence gained in that round trip is not evidence of anything.
We do this to ourselves too, which is the part worth admitting. You hit a symptom, you paste it in, you ask for a fix, and you get one. Then you get the next one. Three fixes deep you are looking at a workaround stacked on a workaround, and every individual step had a good justification, because at no point did anyone ask whether the design underneath was right. The model was answering the question. It was the wrong question, and it was ours.
None of this is an argument against using the tools. This post was written with them, and the note at the bottom of this page says so. It is an argument that agreement is not verification, and that the one thing the model will almost never do unprompted is refuse the premise.
The four questions
There is no clever technique here. There are four questions, and they are useful mostly because they are hard to answer without accidentally saying something true.
What happens if we never build this? This is the first one, always. It forces the cost of doing nothing into the open, where it can be compared against the cost of the work. Sometimes the answer is a specific business consequence with a number attached, and then we are done talking and we build it. Often the answer is a pause, and then a description of something mildly annoying that has been mildly annoying for three years.
Show me the last time this actually hurt. Not the general case, the specific incident. Which day, who was affected, what did they do instead. A real story comes with details a hypothetical never has, and it usually contains the actual problem somewhere in the middle of it. When there is no last time, the feature is being built for an imagined future, which is a legitimate thing to do and a very different conversation to have.
Who asked for this, and what did they literally say? Almost every request has been translated at least once before it gets to us. The original wording carries the problem: someone said they spend their whole Monday fixing the same import. The translation carries the solution: we need a bulk edit screen. Getting back to the first sentence is often the entire job, and it takes about a minute.
Walk me through the workflow without naming a single tool or feature. The most awkward of the four, and the most reliable. Nobody can describe a process in solution-free language without exposing what the process is for. It also breaks the spell of the prototype, because the prototype has a name and the constraint forbids names.
| A good sign | Keep digging |
|---|---|
| A dated incident with names in it | ”It happens all the time” |
| A number someone can defend | ”It would just be much better” |
| The original request quoted verbatim | ”Everyone has been asking for it” |
| A workflow described without product names | A workflow described as a sequence of screens |
When we build X anyway
Sometimes a client hears all four questions and still wants X. That is fine, and it is their call. They own the system, they carry the consequences, and they have context we do not. We are contractors, not the last line of defence against our clients’ decisions.
What changes is that Y is now written down. It went into the notes, it went into the ticket, and when it resurfaces in a year, which it usually does, nobody has to rediscover it from scratch. That is worth the twenty minutes on its own.
Writing things down keeps you honest. It is harder to be vague on paper than in conversation, and a solution with no stated problem next to it looks conspicuously bare.
