Logs, Console & Network Evidence
A screenshot shows that something broke. The console, the network tab, and the server log show what broke, where, and with which exact request. That is the evidence that turns “cannot reproduce” into a fixed ticket.
1 The Hook
A tester on a RealMe-linked government service raises a defect: “Login sometimes fails with a generic error.” She attaches a screenshot of the red banner that says “Something went wrong. Please try again.” The developer reads it, shrugs, and replies: “Generic error could be anything — network, session, the identity provider. I cannot reproduce it. Can you get more detail?” The ticket stalls.
The next tester hits the same failure. Instead of screenshotting the banner, he opens the browser console and sees a logged error. He opens the network tab and finds the failing request — a call to the session-exchange endpoint returning 500. He clicks it, copies the response body, and there is a correlation ID: req-7f3a9c21-be40. He attaches the console error, the failing request with its status and timing, the response body, and that ID. He adds one line: “correlation ID req-7f3a9c21-be40, around 10:42 NZST.”
The developer takes that correlation ID, searches the server logs, and lands directly on the exact stack trace for that one failed request — a null session token when a customer’s RealMe session had expired mid-flow. Fixed that afternoon. Same bug, same banner, same “generic error”. The only difference was that the second tester gathered the evidence the banner was hiding.
The screenshot told the developer that it failed. The evidence told them what failed and gave them a thread to pull. A generic error message is the system politely refusing to tell the user what happened — but it almost always told the console, the network tab, or the log. Learning to read those three places is how you turn a dead-end banner into a fixable report.
2 The Rule
The user-facing error message is the least useful evidence there is — it is deliberately vague. The real evidence lives in the browser console, the network tab, and the server logs, and a correlation ID is the thread that ties all three together. A report that carries that evidence is reproducible by a developer even when the symptom is intermittent; a report that carries only a screenshot of the banner is a guess.
3 The Analogy
A Waka Kotahi crash investigation versus a witness saying “there was a bang”.
A witness who says “I heard a bang and saw smoke” confirms a crash happened, but an investigator cannot act on it. The investigator wants the skid marks, the dashcam footage, and the vehicle’s event-data recorder — the trail that shows speed, braking, and the exact moment of impact. Those let them reconstruct what happened without having been there.
A screenshot of an error banner is the witness saying “there was a bang”. The console error, the failing network request, the response body, and the server log are the skid marks and the dashcam. The correlation ID is the number plate that ties the dashcam clip to the exact vehicle in the registry. Gathering evidence is doing the investigator’s job, not the witness’s.
4 The Three Layers of Evidence
When a web application fails, the truth is recorded in up to three places. A strong report knows which layer holds the answer and reaches for it.
The browser console — what the front end said
The console is where the page’s own code reports errors and warnings: a script that threw, a value that was null, a failed assertion. It is the first place to look, because a front-end failure (a button that does nothing, a screen that will not render) often leaves a clear error here that never reaches the user.
The network tab — what the front end and back end said to each other
The network tab records every request the page made and every response it got back: the URL, the method, the status code, the timing, the request payload, and the response body. When a screen shows “something went wrong”, the failing request here usually carries the real status (a 400, a 500) and a far more specific message than the banner.
The server logs — what the back end actually did
The logs are the back end’s own record: the request it received, the code path it ran, and any exception or stack trace. Testers often cannot see these directly, but you can point the developer straight at the right log entry — and the correlation ID (section 8) is exactly how you do that.
5 Reading the Browser Console
Open developer tools (F12 on most desktop browsers, or right-click and Inspect) and select the Console tab. Reproduce the bug with the console open, because some errors only appear at the moment of failure.
You are looking for entries in red — errors — and to a lesser extent yellow warnings. A typical console error looks like this:
You do not need to debug the code. You need to capture it faithfully. Three things make a console error useful in a report:
- The full error text — copy the message verbatim, not a paraphrase. “Cannot read properties of null (reading ‘balance’)” tells the developer the system tried to read a balance on something that was empty.
- The location — the file and line (
accounts.js:142) point straight at the code. Include the few lines of stack trace shown. - The timing — note that the error appeared exactly when you performed the failing action, so it is tied to the bug and not leftover noise.
Copy the error as text where you can — text is searchable and a developer can paste it into their own tools. A screenshot of the console is a fallback, useful when copy is awkward, but plain text is better.
6 Reading the Network Tab
Select the Network tab in developer tools, then reproduce the bug. Each row is one request the page made. The columns that matter to you are the name (the endpoint), the status, the method, and the time.
Your eye goes to the failures first. A status in the 4xx range means the request was rejected — the client sent something the server would not accept (400 bad request, 401 unauthorised, 403 forbidden, 404 not found, 422 validation failed). A status in the 5xx range means the server itself broke handling the request (500 internal error, 503 unavailable). The distinction is a strong first clue: a 4xx usually points at the request or the client; a 5xx points at the back end.
Click the failing request and you get sub-panels worth capturing:
- Headers — the URL, the method, the status, and the response headers, which often carry a correlation or request ID.
- Payload / request — exactly what the page sent. For a failing payment this might show the amount and account the front end submitted, which can reveal the front end sent the wrong value.
- Response — exactly what the server sent back, usually with a far more specific message than the banner:
{"error":"date must be in the future","field":"scheduledDate"}where the user saw only “Invalid date”. - Timing — how long it took, which matters for timeout and slow-response bugs.
You can also save the whole network capture as a HAR file and attach it, giving the developer the complete request/response trail. Treat a HAR file with care — it can contain tokens and personal data, which brings us to redaction in section 9.
7 Reading Server Logs
Server logs are the back end’s diary. Even when you cannot open them yourself, knowing how they read lets you point a developer to the exact entry. A typical log line is structured:
Read it left to right: the timestamp (with the timezone — note the +12:00 for NZST), the level (ERROR, WARN, INFO — you want ERROR around the moment of failure), the correlation ID in brackets, the component, and the message and stack trace.
The two facts that let a developer find your failure in a log of millions of lines are the timestamp (with timezone) and the correlation ID. If you give them nothing else from the back end, give them those. “It failed around 10:42 NZST, correlation ID req-7f3a9c21-be40” lets them grep straight to the line above.
8 Correlation IDs — the Thread Through Everything
A correlation ID (also called a request ID, trace ID, or transaction ID) is a unique string the system stamps on a single request and carries through every system that request touches — the front end, the API gateway, each back-end service, and the logs. It is the single most valuable piece of evidence you can hand over, because it ties the three layers together.
One request to pay rates might pass through a web server, a payments service, and a bank gateway. Each writes its own log lines. Without a shared ID, finding which lines belong to your failed payment is hunting a needle in millions of lines. With it, the developer searches one ID and sees the whole path of that one request across every system — exactly where it broke and why.
Where to find it:
- In the response headers of the failing request in the network tab — commonly named
x-request-id,x-correlation-id, ortraceparent. - In the response body — many APIs return it alongside an error:
{"error":"...","correlationId":"req-7f3a9c21-be40"}. - On the error screen itself — well-built systems show a reference code to the user precisely so support can trace it: “Something went wrong. Reference: req-7f3a9c21-be40.”
If you can find a correlation ID, it goes in the report every time. It is the difference between “something failed somewhere around 10:42” and “here is the exact request, follow it through every system.”
9 Capturing Payloads Safely
Payloads, response bodies, HAR files, and logs are powerful evidence — and they often contain things that must never be pasted into a ticket. Under the NZ Privacy Act 2020, attaching a customer’s IRD number, full name, date of birth, or a session token to a Jira ticket that dozens of people can read is itself a problem, even though you were trying to do good work.
Before you attach evidence, scan it and redact:
- Authentication secrets — bearer tokens, session cookies, API keys, passwords. A token in a HAR file can let someone act as that user. Replace with
[REDACTED]. - Personal information — IRD numbers, full names, dates of birth, addresses, account numbers, RealMe identifiers. Keep only what the developer needs to understand the failure; mask the rest.
- Card and payment data — full card numbers and CVVs never belong in a ticket. This is the PCI-DSS habit from the banking track.
The goal is to keep the shape of the evidence — the structure of the payload, the error, the correlation ID — while removing the sensitive values. A developer almost never needs the real IRD number to fix the bug; they need to know the field was present and what the system did with it. When in doubt, redact and say so: “payload attached, personal fields masked.”
10 Common Mistakes
🚫 Attaching only a screenshot of the error banner
Why it happens: The banner is what you saw, and screenshotting it is quick.
The fix: The banner is deliberately vague. Open the console and network tab and capture the real error, the failing request and its status, the response body, and any correlation ID. The screenshot proves it happened; the evidence shows what happened.
🚫 Losing the failing request to a page reload
Why it happens: A failure often triggers a redirect or reload, which clears the network tab before you copy anything.
The fix: Tick “Preserve log” in the network tab before you reproduce. Then the failing request survives the reload and you can open it, read the response, and pull the correlation ID.
🚫 Recording the time without a timezone
Why it happens: “Around 10:42” feels precise enough.
The fix: Your developer, the server, and the logging stack may all be on different timezones. Write “10:42 NZST”. A large share of “cannot find it in the logs” cases are simply an offset between two clocks.
🚫 Pasting raw payloads with tokens or personal data into the ticket
Why it happens: You want to give the developer everything, so you attach the whole HAR or response.
The fix: HAR files and payloads carry session tokens, IRD numbers, and card data. Redact secrets and personal information before attaching — or hand over the correlation ID and let the developer pull the detail from the secured logs instead. The Privacy Act 2020 applies to your ticket too.
11 Now You Try
Three graded exercises: read evidence, attach the right evidence, then design an approach for a hard case. Write your answer, run it for AI feedback, then compare to the model answer.
Below is a pasted console error, a network entry, and a server log line from a fictional Kiwibank online bill-payment failure. Read them and answer: what failed, which layer points at the back end, and what is the correlation ID. Then state the one line you would add to the bug report to let a developer find this in the logs.
Answer the four parts:
Show model answer
What failed: The payment request failed with a 500. The specific cause is a timeout on the funds (insufficient-funds) check - the payment service waited 30 seconds for a downstream balance-service that never responded, then errored. The user would have seen only a generic failure. Which layer points at the back end (and why): The 500 status (a server error, not a 4xx client error) and the server log together point at the back end. A 5xx means the server broke handling the request; the log confirms it is a downstream balance-service timeout inside PaymentService, not anything the client sent wrong. The ~30,041 ms timing is the tell - it sat for 30 seconds before failing. Correlation ID: pay-4c8e21a7-d09f (it appears in both the network response body and the server log, which is exactly why it is valuable - it ties the two layers together). One line to add to the report: "Failed at 14:18 NZST, correlation ID pay-4c8e21a7-d09f - balance-service timeout after 30s on the funds check (HTTP 500)." That gives the developer the exact log entry plus the cause. Strong answers name the timeout (not just "it failed"), use the 500 + log to locate the failure at the back end, and pull the correlation ID from where it actually appears.
A thin report against a fictional Te Whatu Ora appointment-booking portal reads: “Booking an appointment fails on the last step. Screenshot attached of the error.” List the specific pieces of evidence you would gather and attach to make this actionable — from the console, the network tab, and the server side — and note what you would redact before attaching. Be concrete, not generic.
Show model answer
From the browser console: the full error text (verbatim) and the file:line and stack-trace lines, captured at the moment of failure; copied as text where possible, not just a screenshot. From the network tab: the failing request (with "Preserve log" ticked so a redirect does not clear it) - its URL, method, and status code (e.g. 400 vs 500, which tells client vs server); the request payload the page sent on the final step; the response body, which usually has a far more specific message than the banner; the timing; and any correlation/request ID from the response headers or body. From the server side: you usually cannot open the logs yourself, so hand the developer the two things that locate the entry - the exact timestamp WITH timezone (e.g. 14:18 NZST) and the correlation ID. Optionally attach a redacted HAR for the full request/response trail. What to redact before attaching: the patient's personal information (name, NHI number, date of birth, contact details), any session token or cookie in the HAR or headers, and any auth secret. Keep the shape of the payload and the correlation ID; mask the sensitive values - the Privacy Act 2020 applies to the ticket. Note "personal fields masked". Strong answers are concrete (named status codes, the correlation ID, "Preserve log", timestamp with timezone) and explicitly handle redaction for a health context.
An intermittent bug: on a fictional BNZ internet-banking dashboard, the account balance occasionally shows as $0.00 on load, then corrects itself if you refresh. It happens maybe one load in ten, with no obvious trigger, and you cannot reproduce it on demand. Design an evidence-gathering approach so that when it next happens, you capture enough to make it actionable. Cover: how you set up before it happens, what you capture in the moment, and how you tie it to the back end.
Show model answer
Set-up before it happens: keep developer tools open on the Network and Console tabs while you work, with "Preserve log" ticked so a refresh does not wipe the evidence. Because it is roughly 1 in 10, do repeated fresh loads (or keep the tab open through normal testing) with capture already running, so you are ready when it fires. Consider a screen recording running so you catch the exact load.
What to capture in the moment it occurs: do NOT refresh first - the refresh hides the evidence. Capture the load where the balance shows $0.00: the request that fetched the balance in the network tab (status, response body - does the API actually return 0, or an error, or empty?), any console error at that moment, the exact timestamp with timezone, and the correlation/request ID from that specific request. Save the HAR of that load. Compare against a good load to show the difference.
How to tie it to the back end / logs: hand over the correlation ID and the timestamp (with timezone) of the bad load so the developer can find that one request in the logs and see what the balance-service returned for it. The key question the evidence answers: did the API return $0.00 (a back-end/data issue) or did the front end fail to read a correct value (a front-end timing/race issue)? The response body settles it.
How to report an intermittent bug honestly: state clearly that it is intermittent and give the observed rate ("about 1 in 10 loads"), the conditions you have noticed, and that it self-corrects on refresh. Attach the captured evidence from the one time you caught it. Never dress an intermittent bug up as deterministic - say what you know, and provide the correlation ID so the developer can investigate from their side.
Strong approaches set up capture in advance (Preserve log, tools open), grab the bad load before refreshing, use the response body to separate front-end from back-end cause, and report the flakiness honestly with a rate and a correlation ID.
12 Self-Check
Click each question to reveal the answer.
Q1: Why is a screenshot of the error banner the weakest evidence you can attach?
User-facing error messages are deliberately vague — “something went wrong” tells the developer nothing about what actually failed. The real detail lives in the console error, the failing network request and its status, the response body, and the server log. The screenshot proves it happened; only the evidence shows what happened.
Q2: What are the three layers of evidence, and what does each tell you?
The browser console — what the front-end code said (script errors). The network tab — what the front end and back end said to each other (requests, status codes, payloads, responses). The server logs — what the back end actually did (the code path and any stack trace). You work outside-in across them.
Q3: What is a correlation ID and why is it so valuable?
A unique string the system stamps on a single request and carries through every system that request touches — front end, gateway, back-end services, logs. It ties the three layers together: a developer searches one ID and sees the whole path of that exact request across every system, finding the failure in millions of log lines instantly. It is the single most valuable piece of evidence to hand over.
Q4: A request fails with a 4xx versus a 5xx status — what does each suggest, and why does it matter?
A 4xx means the request was rejected — the client sent something the server would not accept (bad input, not authorised, not found); it usually points at the request or the client. A 5xx means the server itself broke while handling the request; it points at the back end. The distinction tells the developer which way to look first, before they open anything.
Q5: What must you do before attaching a HAR file or raw payload to a ticket?
Redact it. HAR files and payloads carry session tokens, API keys, and personal information — IRD numbers, names, dates of birth, card data. Mask the secrets and personal values while keeping the shape of the evidence, or hand over just the correlation ID and let the developer pull the detail from the secured logs. The Privacy Act 2020 applies to your ticket too.
13 Interview Prep
Real questions asked in NZ QA interviews. Read the model answers, then practise your own version.
“A page shows ‘Something went wrong’ and nothing else. How do you investigate?”
I treat the banner as the least useful evidence and go to the three layers behind it. First the browser console, with the bug reproduced while it is open, to capture any script error verbatim with its file and line. Then the network tab — with “Preserve log” ticked so a reload does not wipe it — to find the failing request, read its status code (4xx points at the client, 5xx at the back end), and open the response body, which almost always carries a far more specific message than the banner. I pull the correlation ID from the response headers or body. If the failure is on the server side, I hand the developer the correlation ID and the exact timestamp with timezone so they can find that one request in the logs. The banner said “something”; the evidence says exactly what.
“What is a correlation ID and how have you used one?”
It is a unique identifier the system stamps on a single request and carries through every service that request touches — the front end, the gateway, the back-end services, and the logs. Its value is that it ties all the layers together: instead of guessing which of millions of log lines belong to my failure, the developer searches one ID and sees the whole path of that exact request. I use it whenever I can find one — in the response headers, in the response body, or on the error screen as a reference code — and I put it in the report with the timestamp and timezone. It is the difference between “something failed around 10:42” and “here is the exact request, follow it through every system.”
“How do you report a bug you can only reproduce one time in ten?”
I set up to catch it rather than chase it. I keep the console and network tabs open with “Preserve log” on, and often a screen recording running, so when it fires I already have the evidence. In the moment I capture the bad load before refreshing — the failing request, its response body, any console error, the timestamp with timezone, and the correlation ID — because a refresh would hide it. The response body usually settles whether it is a back-end issue or a front-end timing problem. Then I report it honestly: I state it is intermittent, give the observed rate and any conditions I have noticed, attach the evidence from the time I caught it, and provide the correlation ID so the developer can investigate from their side. I never dress an intermittent bug up as deterministic — I say what I know and give them a thread to pull.