In JMeter, what makes an HTTP Request sample count as successful when no assertion is attached?
answer
- Only one line of the reply matters
- The status line, not the body
- One contiguous numeric range decides
- Redirect codes sit inside it
basics
~10 sThe HTTP status code alone decides it. JMeter marks a sample successful for any code from 200 to 399 inclusive, and unsuccessful for 4xx and 5xx. Nothing in the response body is read.
solid answer
~40 sJMeter's HTTP samplers hand the status code to `MetricUtils.isSuccessCode(code)`, which returns true for anything from **200 to 399 inclusive**, and pass that verdict straight to `SampleResult.setSuccessful(...)`. A transport failure takes a different path: the sampler catches the exception, sets the response code to `Non HTTP response code: <exception class>` and marks the sample failed. Everything else about the reply — the body, its size, its content type — is ignored. So a `200` page reading "We are having trouble processing your request", a `302` to a login form, and a zero-byte body all pass. Content is checked only if you add an assertion, and an assertion can lower a sample from success to failure, never raise it — except through the Response Assertion's Ignore Status checkbox, which forces success before the patterns run.
go deeper
Recall that JMeter grades an HTTP sample on its status code alone, and that codes in the 200s and 300s all pass. Nothing visible in the response body changes that verdict.
Explain that the sampler calls isSuccessCode and marks the result successful for 200 to 399 inclusive, and that a transport exception takes the separate Non HTTP response code path instead.
Show how a run reports zero errors while the site serves 200 error pages, and name the specific assertion you would add so the error count means something again.
Decide what a green JMeter run is allowed to be quoted as evidence for when the status range is the only rule in play, and set that expectation before anyone reads the numbers.
JMeter's default verdict for an HTTP sample is a one-line rule, and almost every false-green run in a JMeter plan starts by forgetting it. ## The rule, exactly `HTTPHC4Impl` reads the status line, calls `res.setResponseCode(...)` with the numeric code, and then calls `res.setSuccessful(isSuccessCode(statusCode))`. That helper is `MetricUtils.isSuccessCode(int code)`, whose whole body is `return code >= 200 && code <= 399;`. There is no second condition. The body has not been parsed at that point and never will be unless a later element asks for it. Two consequences follow immediately: - **Redirect codes pass.** `301`, `302`, `303` and `307` all sit inside the range, so a sampler with *Follow Redirects* switched off records a green sample for a redirect to `/login`. - **`4xx` and `5xx` fail.** These are the only status-driven failures JMeter produces on its own. Transport-level trouble is handled separately. When the request throws — connection refused, read timeout, TLS handshake failure — `HTTPSamplerBase.errorResult` writes the stack trace into the response data, sets the response code to `Non HTTP response code: java.net.SocketTimeoutException` (the exception's class name is appended) and calls `setSuccessful(false)`. ## What this lets through The interesting cases are the replies that arrive intact and mean nothing good: | What the server sent | JMeter's verdict | Why | |---|---|---| | `200` with an application error page | success | status in range | | `200` with an empty body | success | size is not examined | | `200` with the login form instead of the requested page | success | content is not examined | | `302` to `/maintenance` | success | `302` is inside 200–399 | | `404` or `500` | failure | status outside the range | | Connection refused | failure | exception path, `Non HTTP response code` | A run that reported **zero errors while serving error pages** is the canonical version of this. The application degraded, its front end started returning a friendly `200` apology page for every request, and every sampler in the plan went on recording a success. The non-GUI summariser lines still read `Err: 0 (0.00%)` all night, because the error count is nothing more than a tally of samples whose success flag was false. ## Nothing else in the plan intervenes It is worth being precise about which elements can and cannot change this verdict, because candidates often assume more machinery exists than does: 1. **Post-processors cannot fail a sample.** A Regular Expression Extractor, a JSON Extractor or a Boundary Extractor that matches nothing writes its Default Value and returns; it never touches the success flag. 2. **Assertions can only lower the verdict.** `JMeterThread.processAssertion` computes `result.setSuccessful(result.isSuccessful() && !(error || failure))`, so an assertion turns a pass into a fail and never the other way round. 3. **The one exception runs the other way.** A Response Assertion with **Ignore Status** ticked calls `response.setSuccessful(true)` before evaluating its patterns, deliberately discarding the sampler's own verdict. 4. **Embedded resources are the one place a property moves the line.** `httpsampler.ignore_failed_embedded_resources` defaults to `false`, so a failed sub-resource fails its parent page sample; set it to `true` and the parent stays green. ## Making the check real The fix is to state, in the plan, what a correct reply looks like: - Add a **Response Assertion** whose *Field to Test* is `Text Response` and whose pattern is something only a genuine reply contains — an `orderId` key, a customer name, a specific element id. - Or set *Field to Test* to `Response Code` and pin the expected code, which also catches an unwanted `302`. - A **Size Assertion** catches the zero-byte reply that a content pattern would also catch but more cheaply. - A **Duration Assertion** catches the slow-but-successful reply that the status rule is blind to. Keep the patterns cheap and specific. The point is not to validate the whole document; it is to give JMeter one fact about the reply that an error page cannot satisfy, so that the run's error count stops being a count of transport failures and starts being a count of wrong answers. ## The takeaway `200–399` is the entire default rule a JMeter plan applies to an HTTP sample. Every other property of the reply is checked only by an element you added, so with no assertion in scope a green JMeter sample reports that the status line was in range and nothing else.
- Does a JMeter sample fail when the connection is refused before any status line arrives?Yes, but by a different route. The sampler catches the exception, puts the stack trace in the response data, sets the response code to `Non HTTP response code:` followed by the exception's class name, and marks the sample unsuccessful. The 200–399 rule only applies to replies that actually carried a status line.
- Which JMeter property stops a failed embedded-resource download from failing its parent sample?`httpsampler.ignore_failed_embedded_resources`, which defaults to `false`. At the default, a page sampler retrieving embedded resources is marked failed if any sub-resource fails, with an `Embedded resource download error:` message naming the URLs. Set it to `true` and the parent sample stays green whatever the sub-samples did.
It is the difference between a courier confirming the parcel was delivered and someone opening the box. JMeter signs for the delivery; only an assertion opens the box.
saying these in an interview costs you the question
- Says JMeter inspects the response body by default
- Thinks a 3xx redirect is recorded as an error
- Believes an empty response body fails the sample
- Reads zero errors as proof the application worked
- Assumes every sampler gets an assertion automatically