Home › Nginx Error Log Analyzer

Nginx error log analyzer: group error.log into distinct problems

Direct answer: drop your Nginx error.log below. Its repeated failures — connect() failed, upstream timed out, no live upstreams, SSL handshake failures — are grouped into distinct problems, each with a count, first and last seen, and redacted samples, ranked by severity × frequency. The values that change between occurrences (client addresses, connection numbers, quoted requests and upstreams) are masked before lines are compared; the server name is not, so two sites sharing one file keep separate rows. Processed locally; nothing is uploaded.

Group this log now

Drop a log file here — or click to choose one. Files are read in slices on this device (designed for logs up to ~500 MB); nothing is uploaded.

How it works

  1. Drop the error.log (or paste an excerpt) into the panel.
  2. Press Group errors. The file is processed in your browser — watch progress, cancel any time.
  3. Read the Triage Board: upstream failures, handshake errors and missing files as distinct problems, ranked by severity × frequency.
  4. Open a group to inspect its pattern and samples; export the incident report if the findings need to travel.

The bracketed word at the start of each line — [error], [warn], [crit] — is read as the entry's severity, and severity drives the ranking together with frequency, so a short burst of critical failures is not buried under a day of warnings.

What grouping does to an error.log

Every error.log line has the same anatomy: date, time, the bracketed level, process and connection numbers, the failure message — then, for request failures, the circumstances: client, server, request, upstream, host. The failure repeats; the circumstances never do. That split is exactly what grouping uses. These three lines are one problem wearing three sets of circumstances:

2026/11/09 06:12:01 [error] 1842#1842: *104729 connect() failed (111: Connection refused) while connecting to upstream, client: 203.0.113.7, server: shop.example.com, request: "GET /checkout HTTP/1.1", upstream: "http://127.0.0.1:3000/checkout", host: "shop.example.com"
2026/11/09 06:12:04 [error] 1842#1842: *104755 connect() failed (111: Connection refused) while connecting to upstream, client: 198.51.100.23, server: shop.example.com, request: "POST /api/orders HTTP/1.1", upstream: "http://127.0.0.1:3000/api/orders", host: "shop.example.com"
2026/11/09 07:40:19 [error] 1843#1843: *105201 connect() failed (111: Connection refused) while connecting to upstream, client: 192.0.2.44, server: shop.example.com, request: "GET /cart HTTP/1.1", upstream: "http://127.0.0.1:3000/cart", host: "shop.example.com"

They come back as a single row — connect() failed while connecting to upstream, count 3, first seen 06:12:01, last seen 07:40:19. Multiply that by a busy morning and the file's thousands of lines become the handful of failures that actually need fixing: the refused upstream, the timed-out report route, the expired upstream certificate behind the SSL handshake failures.

Honest details

Missing files group by failure, not by path. The path in an open() line is a quoted value, and quoted values are masked — so a missing favicon and a missing robots.txt count as one "file not there" problem. The group's samples show the real paths; nothing is hidden, and the tool's "distinguish short quoted strings" option can split them if the paths matter more than the failure on your site.

Server names stay visible. When several sites share one error.log, the same upstream failure under two server blocks appears as two rows — deliberate: the fix, and usually the owner, differs per site, and merging them would understate each one.

Grouping is not diagnosis, and archives need opening first. The board will tell you the upstream refused connections 800 times starting at 06:12 — not why the upstream was down. And drop the plain text file: a rotated .gz archive has to be decompressed before it can be read here.

error.log is not access.log

The access log is the other Nginx file: one line per request, with the status it was answered with. If your question is which routes return 404 or 500, or when traffic peaks, that is Access-Log Triage — and the guide finding errors in an Nginx access log covers the route-pattern method. This page is for the file that explains why those 502s happened. Application logs from behind the upstream (Node, Python, Java and the rest) group on the Error Grouper — the same grouping, framed for stack traces.

Frequently asked questions

What is the difference between error.log and access.log?

The access log records every request — method, path, status, bytes sent — whether or not anything went wrong. The error log records what went wrong while serving them: refused upstream connections, timeouts, failed SSL handshakes, files that were not there. Questions about traffic and statuses belong to the access log; questions about failures belong here. Same server, two files, two different jobs.

Where do I find my error.log?

Wherever the error_log directive in your configuration points — that directive is the authority. On most packaged installs it is /var/log/nginx/error.log, and many setups keep a separate error log per site alongside the global one. With the official Docker image the error log is sent to stderr instead, so the same lines appear in the container log output (docker logs). If the lines start with a date, a time and a bracketed level like [error], you have the right file.

What does grouping do with upstream errors?

It separates the failure from its circumstances. The message — connect() failed, upstream timed out, no live upstreams — is the problem; the client address, connection number, request and upstream values trailing after it change with every occurrence, so they are masked before lines are compared. Eight hundred refused connections to one upstream come back as one problem with a count of 800, a first-seen and a last-seen — and the samples keep real lines (redacted) so you can see which requests were affected.

Why did two different missing files land in one group?

Because the file path in an open() line is a quoted value, and quoted values are masked before grouping — deliberately: on most sites, "favicon.ico is missing" and "robots.txt is missing" are the same operational problem (files the server expects are not there), counted once. The samples inside the group show the actual paths, so nothing is hidden — and if the paths matter more than the failure, the "distinguish short quoted strings" option above splits groups whose short quoted values differ.

Is my error.log uploaded or stored anywhere?

No. The file is read and processed in your browser; nothing is uploaded. Samples on the board and in every export are redacted by default — client IPs, addresses, tokens and passwords that happen to appear in log lines are masked in what is shown, saved and exported. You can switch the on-screen view to raw for your own screen only; exports and saved board data stay redacted regardless.