Inspect error response bodies
A status code tells you something failed. The captured request and response tell you what. MaxoPerf groups failed requests by error type on the run’s Errors tab and keeps redacted samples of the request and response for the engines that expose them, so you debug from real data instead of guessing.
When this helps
Section titled “When this helps”- A 4xx burst that looks like an auth issue but may be a validation error.
- A 5xx whose body names a specific upstream service.
- A test scenario that gets unexpected redirects or HTML error pages.
How to read error bodies
Section titled “How to read error bodies”-
Open the run and switch to the Errors tab.
Run detail, Errors tab. -
Pick a view. By error type groups rows by category and signature, so you see which kinds of failure dominate. By transaction groups the same errors by request label, so you see which requests fail.
-
Select a row. Move between rows with the arrow keys and open one with Enter, or click it. The row shows the category, the signature, how many requests hit it, its share of requests, when it was first and last seen, and a trend sparkline. In By error type, the detail pane also lists the request labels that hit the error.
-
Open a sample. Use the First, Last, or Recent tab to load a captured sample. Each sample shows the request line, headers and body, and the response status, headers and body.
-
Read the body. For JSON and XML bodies, switch between Pretty and Raw, toggle line wrap, or copy the text. A binary body downloads as a file instead of rendering inline.
-
Check the logs. The Logs tab shows what the runner did at the same timestamp. With the logs and the response body you usually know what to fix.
How errors are grouped
Section titled “How errors are grouped”MaxoPerf normalizes each error message into a signature so that the same failure reported with different ids collapses into one row. For example, 404 Product 'a-1' not found and 404 Product 'b-2' not found both produce the signature 404 Product '<str>' not found.
The masking rules:
- UUIDs become
<uuid>. - Hex ids of 8 or more characters become
<hex>. - Email addresses become
<email>. - Numbers of 2 or more digits become
<n>. - Quoted text becomes
'<str>'. - Absolute URLs keep their scheme and host; the path becomes
/<path>(https://demo.maxoperf.com/api/products/blue-shirtbecomeshttps://demo.maxoperf.com/<path>). - A bare path after
for url:(Locust’s error format) becomesfor url: /<path>, so Locust 404s for different slugs share one row. - Query strings become
?<query>. 0x…addresses become<addr>.- Values that look like secrets never survive into a signature: a
password=…-style value becomes<redacted>, aBearer …token becomesBearer <redacted>, aBasic …value becomesBasic <redacted>, and JWTs become<jwt>. Credentials in a URL (https://user:pass@host) becomehttps://<redacted>@host.
Every row also carries a category: Server errors (5xx), Client errors (4xx), Timeouts & network, Assertion failures, or Other errors.
Each row also shows the share of requests that hit the error: of all requests in By error type, of that request label’s requests in By transaction. It shows a dash while any scope filter (time range, location, label, runner, scenario, or the Transactions filter) is active, because the percentage would no longer describe the whole run.
Which engines capture bodies
Section titled “Which engines capture bodies”| Executor | Request and response bodies |
|---|---|
| JMeter, k6, Gatling, Locust, Apiritif, Playwright | Captured |
| Selenium | Chrome only, while browser recording is on for the run and the test’s first execution is Selenium. Samples appear when each browser session ends. Edge and Firefox record metadata only. |
| ab, Siege, pbench, Tsung, Vegeta, Molotov, Grinder, JUnit, TestNG, Mocha, WebdriverIO, Robot | Not captured. The Errors tab shows messages and counts. |
A few limits to know:
- In a test with more than one execution, k6 samples come from the first execution only.
- Selenium samples need the test’s first execution to be Selenium; then every Selenium execution in the run is covered.
- Locust users built on
FastHttpUserare not captured;HttpUseris. - Gatling samples are skipped for the whole run when the test sets its own
JAVA_OPTSorlogback.configurationFile, or when its files include alogback*.xml. Errors still show in the list, without samples. - k6 samples come from virtual users 1 and 2 only. An error that only other virtual users or scenarios hit still shows in the list, but has no sample.
- Requests sent with k6
http.batchorhttp.asyncRequestare not captured. - Locust custom failures (
response.failure(...),CatchResponseError) are recorded by Taurus with code 500, so they appear under Server errors (5xx), unless the failure message names a timeout, a connection error, or an assertion. - Playwright test failures (
Test failed: …) are recorded by Taurus with code 500 or the page’s last navigation status; they appear under Assertion failures, or under Timeouts & network for timeouts and connection errors, never under Server errors (5xx).
For Selenium, browser recording must be on for the run. See Record browser tests: video, HAR, and console steps.
What is kept
Section titled “What is kept”For each combination of runner, scenario, request label, and signature, MaxoPerf keeps the first sample, the last sample, and up to 5 of the most recent samples. A body over 64 KiB is cut and marked Truncated. A run keeps samples for up to 500 distinct combinations of scenario, request label, and error per runner; beyond that, the error is still counted but has no sample. Samples are kept for as long as the run’s other results.
Samples appear while the run is in progress, except for Selenium, where they appear when each browser session ends.
The sample pane tells you which sample it is showing. It prefers a sample that matches this exact error; if there is none, it falls back to a sample with the same status code from the same request label; failing that, it falls back to any sample for that label, and says so. When the Transactions filter is set to anything other than All transactions, the pane shows no samples and says “Samples aren’t linked in filtered views”. Set it back to All transactions to see them.
What is redacted
Section titled “What is redacted”MaxoPerf redacts captured samples before they leave the runner: the request and response bodies, the request URL, headers, and the response message.
- Headers: a fixed list (
Authorization,Proxy-Authorization,Cookie,Set-Cookie,X-Api-Key,X-Auth-Token,X-Amz-Security-Token), plus any header whose name contains a secret word, such asApi-Key,X-Access-Token,Private-Token,X-CSRF-Token, orX-Session-Id. A redacted header shows a Redacted badge. - Bodies, URLs, and messages: JSON, form, and query fields whose name contains
password,passwd,secret,token,api_key/api-key/apikey,authorization,access_key/access-key,client_secret/client-secret,session, orcookie; XML and SOAP elements with such a name (for example<wsse:Password>or<apiKey>); multipart form fields with such a name; credentials in a URL (https://user:pass@hostbecomeshttps://[REDACTED]@host); and anyBearer …orBasic …value, or a JWT, becomes[REDACTED]. - Redaction is pattern-based, matching on field and header names, not on a full understanding of the payload.
- A binary body (one that is not valid UTF-8 text) is not redacted. It is kept as captured and downloads as a file.
Transaction names are shown exactly as your test names them. They are not redacted, so keep secrets out of your labels.
The row’s message and sample messages shown in the Errors list (and in get_run_errors) are not redacted. They come through as the engine reported them. Only captured samples go through redaction.
Engine files you download from the Artifacts tab, such as JMeter’s error.jtl, and browser recording HAR files, contain raw requests and responses and are not redacted. Redacting them is planned.
Turn capture off for a test
Section titled “Turn capture off for a test”Error body capture is on by default. Turn it off (or back on) from a single test’s Configuration tab, under Test details: the Capture error bodies switch saves immediately, with no separate Save step, and applies to the test’s next run. It is only available for single tests. A VarioTest master has no switch of its own; each member uses the setting of its source test.
A re-run of an earlier run reuses that run’s original bundle, so it keeps that run’s capture setting. Runs recorded before this feature shipped stay without bodies even when re-run.
See Test detail: Configuration.
Runs recorded before error grouping
Section titled “Runs recorded before error grouping”Runs from before error grouping shipped still show their errors, grouped by status code under a Recorded before error grouping banner instead of by category and signature.
When the body alone is not enough
Section titled “When the body alone is not enough”If the captured body is empty or does not help (for example, an HTML error page that does not name the cause), try these next:
- Send the same request to the target by hand and compare the responses.
- Check whether the test data variant is missing a required field. See Data entities, parameters, and variants.
- Confirm your secrets are bound correctly. See Manage test secrets.
Use it from an AI assistant
Section titled “Use it from an AI assistant”An MCP-connected assistant reads the same data. get_run_errors returns the grouped rows, each with a signature, category, label, count, responseCode, and a sample message. Follow up with get_run_error_bodies, filtered by signature from that row. If that returns nothing, because the sample’s own error text differs from the row’s status line, retry with the row’s label and response_code, then with label and the row’s category. Never retry with label alone, because that also returns the bodies of other errors on the same transaction. Body text comes back only when you pass a specific row_id: the default concise format returns a short snippet, and response_format: "detailed" returns the full redacted body.
To turn capture off when creating a single test, pass capture_error_bodies: false to create_test (the server default is true). VarioTests take the setting from each member’s source test. See MCP tools reference.
Where to go next
Section titled “Where to go next”- Read run results and logs: the full reading order for a finished run.
- Run stuck or failed: diagnose run-level failures.
- Build reporting dashboards: pin an error-rate chart so you spot regressions early.