Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for NGINX By James Joyner IV · · 9 min read

NGINX Error Guide: '[emerg] directive is not allowed here' and duplicate location

Fix NGINX [emerg] directive is not allowed here and duplicate location errors: diagnose wrong-context directives, missing braces, stray http blocks, and clashing locations.

  • #nginx
  • #troubleshooting
  • #errors
  • #config

Overview

[emerg] "<directive>" directive is not allowed here and [emerg] duplicate location "<path>" are configuration-parse errors. NGINX validates structure before serving anything: every directive is only legal in certain contexts (main, http, server, location, upstream, …), and you cannot define the same location path twice in one server. When a directive sits in the wrong block, or a location clashes, NGINX refuses to load the config — a reload keeps the old config running, a cold start fails entirely.

Typical lines from nginx -t:

nginx: [emerg] "server" directive is not allowed here in /etc/nginx/conf.d/app.conf:42
nginx: [emerg] "location" directive is not allowed here in /etc/nginx/conf.d/app.conf:8
nginx: [emerg] duplicate location "/api/" in /etc/nginx/conf.d/app.conf:30

The message always cites the exact file and line. These are deterministic and entirely fixable from the config — no runtime state involved.

Symptoms

  • nginx -t fails with [emerg] ... directive is not allowed here or duplicate location.
  • systemctl reload nginx reports failure; the running config is unchanged.
  • A cold systemctl start nginx fails and the service stays dead.
  • The message points at a specific file and line number.
sudo nginx -t
nginx: [emerg] "location" directive is not allowed here in /etc/nginx/conf.d/app.conf:8
nginx: configuration file /etc/nginx/nginx.conf test failed
sudo systemctl reload nginx
nginx.service: Control process exited, code=exited, status=1/FAILURE

Common Root Causes

1. A directive placed in the wrong context

location, server, proxy_pass, index, etc. each belong to specific blocks. A location written directly under http {} (not inside a server {}), for example, is illegal.

sudo nginx -t
sed -n '1,12p' /etc/nginx/conf.d/app.conf
http {
    location / {          # <-- location is not allowed directly in http
        proxy_pass http://127.0.0.1:8000;
    }
}
nginx: [emerg] "location" directive is not allowed here in /etc/nginx/conf.d/app.conf:8

location must live inside a server (or another location). Wrap it in a server {} block.

2. A stray or duplicated http block

Files in conf.d/ are already included inside the main http {}. Adding another http {} inside them nests http in http, which is illegal.

grep -RnE '^\s*http\s*\{' /etc/nginx/nginx.conf /etc/nginx/conf.d/
/etc/nginx/nginx.conf:17:http {
/etc/nginx/conf.d/app.conf:1:http {     # extra, nested inside the main http
nginx: [emerg] "http" directive is not allowed here in /etc/nginx/conf.d/app.conf:1

conf.d/*.conf should contain server {} blocks only — remove the redundant http {} wrapper.

3. A missing or unbalanced brace

An unclosed { makes NGINX think a later directive is inside a block that does not accept it, producing a misleading “not allowed here” pointing past the real mistake.

grep -cE '\{' /etc/nginx/conf.d/app.conf
grep -cE '\}' /etc/nginx/conf.d/app.conf
6
5      # one fewer closing brace than opening
nginx: [emerg] "server" directive is not allowed here in /etc/nginx/conf.d/app.conf:42

Brace counts differ; an earlier block was never closed. Fix the missing } (often just above the cited line).

4. Duplicate exact-match location in one server

Two location /api/ {} blocks (same prefix, same server) cannot coexist.

grep -nE 'location\s' /etc/nginx/conf.d/app.conf
12:    location /api/ {
30:    location /api/ {     # exact same prefix in the same server
nginx: [emerg] duplicate location "/api/" in /etc/nginx/conf.d/app.conf:30

Merge the two blocks, or differentiate them (different prefix, or regex vs prefix with ~/=).

5. A server-only directive used in location (or vice versa)

Directives like server_name or listen are not valid inside location; some location-level directives are not valid at server level.

sed -n '20,28p' /etc/nginx/conf.d/app.conf
location /admin/ {
    server_name admin.example.com;   # server_name is not allowed in location
}
nginx: [emerg] "server_name" directive is not allowed here in /etc/nginx/conf.d/app.conf:22

server_name belongs in the server block. Move it up one level.

6. An included snippet broken or in the wrong context

An included file contains directives valid only in a different context than where it is included, so the error points into the snippet.

grep -RnE 'include' /etc/nginx/conf.d/app.conf
sudo nginx -t
include snippets/proxy.conf;
nginx: [emerg] "location" directive is not allowed here in /etc/nginx/snippets/proxy.conf:3

The snippet defines a location but is included at http level. Include it where its directives are legal (inside a server or location).

Diagnostic Workflow

Step 1: Run nginx -t and read the file:line

sudo nginx -t

The [emerg] line names the file and line number of the offending directive (or the duplicate location). That is your starting point — though for brace errors the real cause is often earlier.

Step 2: Look at the cited line in context

sed -n '1,50p' /etc/nginx/conf.d/app.conf | cat -n

Identify which block the directive is actually inside. Ask: is this directive legal in this context? Cross-check against the NGINX directive index if unsure.

Step 3: Check brace balance

grep -cE '\{' /etc/nginx/conf.d/app.conf
grep -cE '\}' /etc/nginx/conf.d/app.conf

Unequal counts mean a missing/extra brace upstream is shifting everything into the wrong context. Fix the imbalance first — it often resolves a misleading “not allowed here”.

Step 4: For duplicate location, list every location in the server

grep -nE 'location\s' /etc/nginx/conf.d/app.conf

Find the two identical prefixes in the same server. Merge their contents into one block, or make one a regex/exact match so they no longer collide.

Step 5: Validate again, then reload

sudo nginx -t
sudo systemctl reload nginx

nginx -t must print test is successful before you reload. Never reload on a failed test — at best nothing changes, at worst a cold restart fails.

Example Root Cause Analysis

A teammate adds a new proxy block and the deploy’s systemctl reload nginx fails. The running site is unaffected (old config still loaded), but the new route never appears.

Running the test:

sudo nginx -t
nginx: [emerg] "location" directive is not allowed here in /etc/nginx/conf.d/api.conf:3
nginx: configuration file /etc/nginx/nginx.conf test failed

Looking at the file:

sed -n '1,10p' /etc/nginx/conf.d/api.conf | cat -n
1  location /api/ {
2      proxy_pass http://127.0.0.1:9000;
3  }

The file defines a bare location with no enclosing server {}. Since conf.d/*.conf is included at http level, a top-level location is illegal — it must be inside a server.

Fix: wrap the location in a server block, validate, and reload:

server {
    listen 80;
    server_name api.example.com;

    location /api/ {
        proxy_pass http://127.0.0.1:9000;
    }
}
sudo nginx -t
sudo systemctl reload nginx
nginx: configuration file /etc/nginx/nginx.conf test is successful

The new route loads.

Prevention Best Practices

  • Always run nginx -t before every reload and gate deploys on it; these are parse errors caught instantly, so no broken config should ever ship.
  • Keep conf.d/*.conf files to server {} blocks (and upstream {}) only — never wrap them in another http {}, which is already provided by nginx.conf.
  • Use an editor with brace matching / NGINX syntax highlighting; the majority of “not allowed here” errors are a missing } shifting context.
  • Name and scope include snippets by the context they belong to (e.g. snippets/proxy_location.conf included only inside a location) so they cannot be pasted into the wrong block.
  • Review location prefixes when adding routes to avoid duplicates; prefer exact (=) or regex (~) matches where intent is specific.
  • For a quick read of a failed nginx -t, the free incident assistant can map the [emerg] line to the wrong-context or duplicate cause. More fixes live in the NGINX guides.

Quick Command Reference

# Validate and read the offending file:line
sudo nginx -t

# Inspect the cited area with line numbers
sed -n '1,50p' /etc/nginx/conf.d/app.conf | cat -n

# Check brace balance
grep -cE '\{' /etc/nginx/conf.d/app.conf
grep -cE '\}' /etc/nginx/conf.d/app.conf

# Find stray http blocks and all locations
grep -RnE '^\s*http\s*\{' /etc/nginx/nginx.conf /etc/nginx/conf.d/
grep -nE 'location\s' /etc/nginx/conf.d/app.conf

# Re-validate and reload
sudo nginx -t && sudo systemctl reload nginx

Conclusion

[emerg] ... is not allowed here and duplicate location are structural config errors NGINX rejects before serving. The usual root causes:

  1. A directive placed in the wrong context (e.g. location directly in http).
  2. A stray/nested http {} inside a conf.d file.
  3. A missing or unbalanced brace shifting later directives into the wrong block.
  4. Two identical location prefixes in the same server.
  5. A server-only directive used in location (or vice versa).
  6. An included snippet pulled into the wrong context.

The error always cites a file and line — check the directive’s context there, fix braces first, then nginx -t until it reports success before reloading.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.