nginx自定义错误页必须同时满足四个条件:error_page配置正确、对应拦截开关(proxy_intercept_errors或fastcgi_intercept_errors)开启、静态资源路径可访问且权限正确、文件大小≥512字节;缺一则显示默认页或浏览器兜底页。

直接说结论:Nginx 自定义错误页不是“改个 HTML 就行”,必须同时满足 error_page 配置、对应拦截开关开启、静态资源路径可访问、文件大小合规这四个条件,缺一不可;否则页面根本不会显示,你看到的还是默认的简陋提示或浏览器兜底页。
为什么 error_page 配置了却没生效?
最常见原因是拦截开关没开——Nginx 默认不接管后端返回的错误状态码。你得根据实际后端类型显式启用对应指令:
- 后端是 PHP(FastCGI):必须在
http或server块中加fastcgi_intercept_errors on; - 后端是反向代理(如 Tomcat、Node.js、Go API):必须用
proxy_intercept_errors on; - 两者都用?两个指令都加上,互不影响
- 漏掉任意一个,
error_page 404 /404.html就只是摆设,请求仍会透传原始 404 状态和默认体
502 错误页为何总显示默认文本而不是你的 HTML?
502 Bad Gateway 是网关层错误(上游连不上),它不来自后端应用,所以不受 fastcgi_intercept_errors 控制,只认 proxy_intercept_errors on;。但还有个关键细节:
-
error_page 502 /50x.html;默认会把响应状态码改成200,掩盖真实问题,不利于前端识别或监控告警 - 要保留原始
502状态码,必须写成error_page 502 =502 /50x.html; - 如果你的前端 JS 依赖
response.status === 502做重试逻辑,不加=502就会失效 - 同理,
error_page 404 =404 /api-404.json;对 API 路径才合理
自定义页面不显示,可能卡在文件路径或大小上
即使配置全对,页面仍不出现,大概率是这两个硬性限制被忽略:
-
location = /404.html中的root路径必须精确匹配文件物理位置。比如配置了root /usr/share/nginx/html;,那你的文件就得在/usr/share/nginx/html/404.html,而不是/var/www/html/404.html - IE 和部分旧客户端要求自定义错误页体积 ≥ 512 字节,否则强制显示浏览器内置页。一个空行+几行文字很容易踩坑,建议用
wc -c /path/to/404.html检查 - 图片/CSS 引用必须走相对路径或绝对路径,且确保该资源能被 Nginx 直接服务(比如
src="/img/logo.png"要有对应location /img/ { alias /var/www/errors/img/; })
API 和 Web 页面混用时怎么区分返回格式?
不能所有路径都塞同一个 /404.html。真实场景里,/api/users/999 返回 HTML 是反模式,应返回 JSON;而 /blog/missing 才该渲染友好页面:
- 用
location ^~ /api/单独配一组error_page:error_page 404 =404 /api-404.json; - 主
server块配通用页:error_page 404 /404.html; - 注意顺序:Nginx 匹配
location是最长前缀优先,^~ /api/必须写在通用location /之前,否则会被覆盖 - 如果用了 Lua 或 NJS,还能动态注入
$upstream_status到 HTML,比如显示“上游服务超时(504)”,比静态文案更准
真正麻烦的从来不是写 HTML,而是让 Nginx 在各种错误来源(静态文件缺失、FastCGI 崩溃、上游失联、超时)下,用正确的开关、正确的状态码、正确的路径,把正确的页面推给正确的客户端——每个环节断一环,就退回默认黑框白字。











