How do support engineers tell whether a customer issue is a bug or expected behavior before escalating?
Run four checks before you escalate. Reproduce the issue on the customer's version and settings. Find the code path that produces it. Search closed issues and Slack for an earlier decision. Then check the release that changed it. A deliberate check in code or a recorded decision means expected behavior. A recent change nobody planned usually means a bug.
To tell a bug from expected behavior, a support engineer needs evidence of intent, not just a repro. Run four checks in order: reproduce the issue, find the code path behind it, look for an earlier decision in closed issues and Slack, and check the release that changed it. Expected behavior is what the product does on purpose, written down in the code, a ticket or a thread where someone chose it. If you can point to that choice, it is not a bug, even if the customer hates it. If the behavior changed recently and nobody chose the change, it probably is a bug.
| Check | Points to expected behavior | Points to a bug |
|---|---|---|
| Reproduce | Only on an old version, plan or flag | Reproduces on the current version |
| Code path | A deliberate condition causes it | An unhandled case causes it |
| Past decisions | A closed issue or thread chose it | No record that anyone chose it |
| Release | A pull request changed it on purpose | It changed as a side effect |
Reproduce it on the customer's version, then write down what "expected" means#
Start by making the issue happen yourself, on the same plan, version, region and settings the customer has. Many "bugs" vanish here. The customer is on an older client, a feature flag is off for their account, or a limit applies to their plan and not yours.
Researchers have a name for these. An invalid bug report is one that does "not require code changes" and is "resolved with a no-code fix," according to a May 2026 study of bug report triage (Gon et al., arXiv). The authors built a hand-labeled benchmark of invalid reports, sorted into types such as Working as Designed, Non-reproducibility and Wrong Version. Language models did well at spotting non-reproducible reports, at 0.85 F1. They did worst on Wrong Version, scoring between 0.00 and 0.29. So if an AI tool does your first pass, check the customer's version yourself.
If it reproduces, write one sentence: "The customer expected X and got Y." Then ask where X came from. If the help center promises X, you have a documentation question or a bug. If X came from the customer's own assumption, the product may be doing exactly what it was built to do. The help center is a weak tiebreaker, since it is often the last thing updated after a change.
Find the code path that produces the behavior#
The code is the most direct record of what the product does today. Take the error message or the odd value and find where it comes from. You are looking for one thing: is there a deliberate condition that causes this? A check such as "reject exports over 50,000 rows" or "skip archived users" is a decision someone made. A null value passed into a function that did not expect it is a mistake.
Support engineers rarely have repository access. Our answer on getting product answers without GitHub access covers that part. With Unblocked, a support engineer might ask in Slack or the web app, "why does the export stop at 50,000 rows?" The answer is drawn from the code, the pull request that added the limit and the related Jira and Slack history, with each source linked at the bottom (Unblocked docs). The point of the citation is that you can open the pull request yourself before you tell the customer anything. Our walkthrough of how the Unblocked context engine ranks sources explains why the code outranks an older wiki page.
Search closed issues and Slack for an earlier decision#
Many "is this a bug?" questions were already asked and answered. The answer sits in a closed issue or a thread nobody linked to the help center. In GitHub, is:closed reason:"not planned" finds issues the team closed on purpose without a fix. That is often a direct record of "this is expected." is:closed reason:completed with linked:pr finds issues closed by a pull request, which points you to the fix (GitHub Docs).
In Slack, search the error text in quotation marks to match the exact phrase. Narrow it with in: for the engineering or product channel and during: for the month the behavior started (Slack). For example, "export limit" in:#product-questions during:september might turn up the thread where a product manager set the limit. A decision with a name and a date on it is the strongest evidence of expected behavior you will find. A decision from two years ago may have been reversed since, which is why the code check comes first. Our answer on what happens when the wiki and the code disagree explains how to weigh an old thread against current code.
Check the release that changed it#
Ask the customer when it started. "It worked last week" is the most useful sentence in a bug report, because it points to a release. If your team uses GitHub releases, automatically generated release notes include "a list of merged pull requests, a list of contributors to the release, and a link to a full changelog" (GitHub Docs). Scan that list for a pull request that touches the feature in question.
What you find decides the label. If a pull request changed the behavior on purpose and its description says so, the behavior is expected, and the real problem is that nobody told customers. That goes to whoever owns the docs or the changelog, not to an engineer's bug queue. If the change came from a pull request about something else, such as a refactor or a dependency upgrade, you are likely looking at a regression. A regression is behavior that used to work and broke as a side effect of a change aimed elsewhere. Regressions are the escalations that should move fastest.
What to put in the escalation when it is still unclear#
Some tickets stay unclear after all four checks. Escalate those, and attach what you found so the engineer starts where you stopped:
- The repro steps, with the customer's version and settings.
- The code path or pull request you think is involved, linked.
- Any closed issue or Slack thread that looks like a past decision, linked.
- The release in which the behavior first appeared, if you know it.
If you run support in Jira Service Management, a linked work item "can help your service space team track which bugs are being handled by the development team" (Atlassian). Linking the request to the bug keeps the customer's ticket tied to the fix.
The same questions come back every quarter. Our post on codebase answers for product and support covers how teams stop re-answering them. Our guide to context for support and ops agents covers what a support bot needs before it can take the first pass.


