nginx: [emerg] unexpected end of file at 2 a.m. almost always means one
thing: somewhere in a few hundred lines of config, a ; or a } is
missing — and Nginx will not tell you where. Nginx’s configuration syntax
(directives terminated by semicolons, { } blocks nesting contexts like
http, server, and location — see the
official beginner’s guide)
is simple, but hand-edited files drift into inconsistent indentation that
hides exactly these mistakes. This formatter re-indents your file by brace
depth and flags the structural errors, entirely in your browser.
A tokenizer, not a regex
The tool runs a pure-JavaScript tokenizer rather than a regex search-and-replace. It walks the source character by character, tracking whether it is inside single quotes, double quotes, or a comment, and emits a formatted statement whenever it reaches a ;, an opening {, or a closing }.
Indentation is driven by brace depth: every opening brace increases the indent level and every closing brace decreases it. Because the parser respects quoting, a # or brace inside a quoted value is treated as data, not as a comment or block boundary.
Validation rules
The formatter reports three classes of problem:
- A directive line whose text does not end in
;,{, or}— flagged as a likely missing semicolon. - A closing
}with no matching open block at that point. - Any blocks still open when the file ends, with a count of how many
}are missing.
Common Nginx config errors this catches
Missing semicolons are the most frequent cause of nginx -t failures. A directive like:
server_name example.com
has no trailing ;, so Nginx treats the next line as a continuation. The formatter flags the offending line immediately.
Unbalanced braces happen when you paste a server block or location block without its closing }, or accidentally delete one during editing. A file with five opening braces but only four closing braces will fail to parse; the formatter counts them and reports how many are missing.
Inconsistent indentation does not cause errors but makes large configs very hard to audit, especially when multiple engineers edit the same file. Re-indenting to a consistent 2 or 4 spaces makes the block hierarchy immediately visible.
Copy-paste artifacts are the sneakiest class: smart quotes pasted from
a chat client or wiki ("…" instead of "…"), non-breaking spaces from a
PDF, or a BOM at the top of the file all produce parser errors whose line
numbers point somewhere unhelpful. Because this formatter tokenizes
character by character, a directive that refuses to terminate cleanly
after pasting is a strong hint the whitespace or quoting characters are
not what they look like — retype the line by hand.
What this tool does not check
The formatter validates structure, not semantics. It will not tell you that proxy_pass cannot appear in an http context, or that you have set worker_processes auto twice. It also will not catch typos in directive names — server_naem formats perfectly but will still fail Nginx’s parser. After formatting, always run:
nginx -t
before reloading, and:
nginx -s reload
only once the test passes. The format step catches the structural mistakes that would otherwise require reading through hundreds of lines of config to find manually.
Multi-file configs and include
Production Nginx setups are rarely one file: nginx.conf typically pulls
in conf.d/*.conf and sites-enabled/* via include directives. Two
formatter-relevant consequences follow. First, brace balance is checked
per file — a server block split across an include boundary is invalid
in Nginx anyway, so a per-file imbalance this tool reports is always a
real error. Second, when you paste a fragment (say, one location block)
the “unclosed block” warning may just reflect the missing outer context;
paste the enclosing server { } shell around it if you want a clean
check. Formatting each included file separately keeps diffs small and
reviews sane.
Context nesting cheat sheet
When re-reading a freshly formatted file, this is the hierarchy the indent levels should reflect:
| Context | Lives inside | Typical contents |
|---|---|---|
main (top level) | — | worker_processes, user, error_log |
events | main | worker_connections |
http | main | include, upstream, server, gzip/log settings |
server | http | listen, server_name, location, TLS directives |
location | server (nestable) | proxy_pass, try_files, root |
If the formatter’s output shows a location block at indent level 1, you
have found a real problem — it is outside any server block and
nginx -t will reject it. The full directive-by-context reference lives
in the official Nginx documentation.
Privacy
Everything runs locally in your browser using JavaScript. Your configuration — which may contain internal hostnames, upstream addresses, or path patterns — never leaves your device and is never uploaded anywhere.
Sources
- Nginx official documentation — directive and context reference
- Nginx beginner’s guide — configuration file structure
The formatter checks structure only; nginx -t remains the authority on
whether a config is valid.