- ネットワーク
500エラーとは|Internal Server Errorの原因と直し方を実例で
結論
500エラーは、サイトのサーバー側で想定外の問題が起きて、ページを返せなかったという意味です。見ている人の端末ではなく、サイト側で直すエラーです。
この記事でわかること
- 見ている人の対処4つとサイト側の原因9種の早見表
- Flask・PHP・nginx・Apacheで起こした500のログ原文
- 本番で詳しいエラーを出さない設定と200に戻す手順
500 は「Internal Server Error(内部サーバーエラー)」の番号です。同じ500でも、見ている人(閲覧者)とサイトを作る人(運営者・開発者)では、やることがまったく違います。
flowchart TD
E[500エラーが出た] --> Q{あなたは?}
Q -->|見ている人| V[少し待って再読み込み<br>直らなければサイトに連絡]
Q -->|サイトを作る人| L[エラーログを見る]
L --> F[原因を直す]
F --> OK[200 に戻る]
よく調べられることの答えを先にまとめます。
| 知りたいこと | 答え | 詳しい節 |
|---|---|---|
| 500エラーとは | サーバー内部の想定外の問題で返せなかった | 500エラーとは |
| 見ている人の直し方 | 数分待って再読み込み。送信の直後なら履歴を確認 | 見ている人の対処 |
| 自分だけ? | 多くはサイト側。別の端末・回線で同じなら確実 | 見ている人の対処 |
| HTTP ERROR 500(Chrome) | 本文が空の500をChromeが表示した画面 | 画面の表示例 |
| サイト側の原因 | プログラムの例外・設定の誤り・権限・メモリ・時間切れ | よくある原因 |
| まず見る場所 | アプリのログとWebサーバーのerror.log | ログの見方 |
| WordPressで出た | .htaccess・プラグイン・テーマ・メモリの順に切り分け | WordPressの500 |
| 502・503・504との違い | 500は主にアプリ自身、502〜504は主に中継役が返す | 502・503・504との違い |
確認環境:Ubuntu 24.04.4 LTS(Linux カーネル 6.18)の上で、Python 3.11.15・Flask 3.1.3(Werkzeug 3.1.8)、PHP 8.4.21 の組み込みサーバー、nginx 1.24.0(Ubuntu)、Apache 2.4.58(Ubuntu)を 127.0.0.1 のポートで動かし、わざと500を起こしてから直しました。応答は curl 8.5.0 の curl -i、ブラウザの表示は Chromium 141.0.7390.37(日本語の画面)で確かめています。500の意味と 5xx の一覧は MDN、Flask の挙動は Flask の公式ドキュメント、PHP の設定は PHP マニュアル、nginx・Apache の挙動は nginx.org と Apache HTTP Server の公式ドキュメント、WordPress の手順は WordPress の公式ドキュメントとソースコード、検索への影響は Google 検索セントラルで確かめました(確認日 2026年10月23日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「500エラーとは|Internal Server Errorの原因と直し方を実例で」
500エラー(500 Internal Server Error)とは
この節では、500エラーが何を意味し、誰の側の問題なのかが分かります。
500 Internal Server Error は、サーバーが予期しない状況に出会い、リクエストに応えられなかったことを示す HTTP のステータスコード(サーバーが返す3桁の結果番号)です。 仕様は RFC 9110 の 15.6.1 で決められています。MDN は次のように説明しています。
サーバーが予期せぬ状況に遭遇し、リクエストの履行が妨害されたことを示します。このエラーは、サーバーの課題に対する一般的な「すべてをカバーする」レスポンスであり、サーバーがレスポンスとして返すのにより適切な 5XX エラーを見つけられなかったことを示します。
言いかえると、500 は「サーバー側で何かがうまくいかなかった」ときの、最後の受け皿の番号です。もっと合う番号(メンテナンス中の 503 など)があればそちらが返り、どれにも当てはまらない想定外の問題が 500 になります。
1サーバー側の問題
5 で始まる番号はサーバー側のエラー。見ている人の操作や端末が原因になることは少ない。
2原因は1つではない
MDN は、サーバー設定の誤り・メモリー不足・処理されない例外・ファイル権限の誤りなどを例に挙げている。
3答えはログにある
画面には理由がほとんど出ない。理由はサーバーのエラーログに書かれる。
MDN は、500 を目にしたら「サーバーの所有者または管理者が調査を行う必要があります」と書いています。つまり、見ている人ができることは限られていて、直すのはサイト側です。
500エラーが出たときの対処(見ている人向け)
この節では、ページを見ようとして500が出たときに、見ている人ができることと、してはいけないことが分かります。
サイト側の問題なので、少し時間をおいて再読み込みし、直らなければサイトの運営者に知らせます。 端末の設定を変えたり、アプリを入れ直したりしても、サイト側の原因は直りません。
数分おいて再読み込みする
一時的な負荷や更新作業の途中なら、時間をおくと直ることがある。Chrome の「HTTP ERROR 500」の画面にも「再読み込み」のボタンがある。
ほかのページを開いてみる
トップページは開けて特定のページだけ500なら、そのページの処理に問題がある。全部500ならサイト全体の問題。
公式のお知らせを見る
サービスの障害情報のページや公式の SNS に、障害やメンテナンスの案内が出ていないかを見る。
日時と URL を添えて知らせる
長く直らなければ、問い合わせ窓口に「いつ・どの URL で・何をしたとき」を伝える。画面にお問い合わせ番号があれば一緒に伝える。
- 購入・予約・送信の直後に500が出たら、何度も送信し直さないようにします。 500 は「処理が途中まで進んだかどうか」を教えてくれません。完了メールや注文履歴を見て、処理が通っていないことを確かめてから、もう一度操作します。
- 「自分だけかどうか」は、別の端末や別の回線(スマホの Wi-Fi を切ってモバイル回線にする等)で開くと分かります。 同じ URL で同じ500が出るなら、サイト側の問題です。
- ログインしているときだけ500になる場合は、サイトが自分のアカウントのデータを処理するところで失敗していることがあります。その場合も、直すのはサイト側です。
500エラーの画面の表示例(Chromeの「HTTP ERROR 500」など)
この節では、500のときにブラウザに何が表示されるのか、表示の違いから何が分かるのかが分かります。
500の画面はサイトによって違います。 サーバーのソフトが用意した画面、サイトが自分で作った画面、そして本文が空のときにブラウザが出す画面があります。手元で500を起こし、Chromium(日本語の画面)で開いたときの表示を並べました。
| 起こした場所 | ブラウザに見えた表示 |
|---|---|
| PHP(エラーを画面に出さない設定) | このページは動作していません/127.0.0.1 では現在このリクエストを処理できません。/HTTP ERROR 500 |
| Flask(Python) | Internal Server Error/The server encountered an internal error and was unable to complete your request. … |
| nginx が自分で返した500 | 500 Internal Server Error/nginx |
| Apache が自分で返した500 | Internal Server Error/The server encountered an internal error or misconfiguration … |
| 自分で用意したエラーページ | ただいま表示できません/時間をおいて再度お試しください。 |
Chrome の「このページは動作していません」「HTTP ERROR 500」は、サーバーが本文の無い500を返したときに、ブラウザが代わりに出す画面です。 PHP の組み込みサーバーで、エラーを画面に出さない設定のまま致命的なエラーを起こすと、応答は次のとおり本文が空でした。これを Chromium で開くと、上の表の1行目の画面になりました。
$ curl -i http://127.0.0.1:30311/fatal.php
HTTP/1.0 500 Internal Server Error
X-Powered-By: PHP/8.4.21
Content-type: text/html; charset=UTF-8
(本文なし)
本文があるときは、Chromium はサーバーが返した HTML をそのまま表示しました(表の2行目以降)。画面の英文やソフトの名前を見ると、どの層が500を返したのかの手がかりになります。
HTTPステータスコードの中の500の位置(5xxの一覧)
この節では、500が HTTP ステータスコードのどこに属し、ほかの 5xx とどう違うのかが分かります。
ステータスコードは、先頭の数字で5つに分かれます(MDN)。
| 番号の範囲 | 分類 | 例 |
|---|---|---|
| 100〜199 | 情報レスポンス | 100 Continue |
| 200〜299 | 成功レスポンス | 200 OK |
| 300〜399 | リダイレクトメッセージ | 301・302 |
| 400〜499 | クライアントエラーレスポンス | 400・403・404 |
| 500〜599 | サーバーエラーレスポンス | 500・502・503・504 |
5xx(サーバーエラー)の一覧です。名前と意味は MDN の日本語版によります。
| コード | 名前 | 意味(MDN) |
|---|---|---|
| 500 | Internal Server Error | サーバー側で処理方法がわからない事態が発生した |
| 501 | Not Implemented | そのリクエストメソッドにサーバーが対応しておらず、扱えない |
| 502 | Bad Gateway | ゲートウェイとして動作するサーバーが無効なレスポンスを受け取った |
| 503 | Service Unavailable | サーバーはリクエストを処理する準備ができていない |
| 504 | Gateway Timeout | ゲートウェイとして動作するサーバーが時間内にレスポンスを得られない |
| 505 | HTTP Version Not Supported | リクエストで使用した HTTP のバージョンにサーバーが対応していない |
| 506 | Variant Also Negotiates | サーバーに内部構成エラーがある |
| 507 | Insufficient Storage(WebDAV) | 必要な表現を保存できず、メソッドを実行できなかった |
| 508 | Loop Detected(WebDAV) | リクエストの処理中に無限ループを検出した |
| 510 | Not Extended | リクエストをさらに拡張することが必要 |
| 511 | Network Authentication Required | ネットワークでアクセスするために認証が必要 |
全部のステータスコードの原因と対処は、関連記事「HTTPステータスコード 一覧|全コードの原因と対処・curl実例つき」で扱っています。
500エラーのよくある原因(一覧)
この節では、サイト側で500になる代表的な原因と、どのログに何が出るのかが一覧で分かります。
500の原因は、大きく「プログラムの誤り」「設定の誤り」「サーバーの資源(メモリ・時間・ディスク)」の3つに分かれます。 下の表の「手元で確かめた」の列は、この記事の後の節で実際に起こして、ログの原文を載せたものです。
| 原因 | ログに出る文言の例 | 手元で確かめた |
|---|---|---|
| プログラムの例外(バグ・想定外の入力) | ZeroDivisionError: division by zero(Flask) |
Flask・PHP |
| 呼び出した関数が無い・文法の誤り | Call to undefined function / Parse error(PHP) |
PHP |
| メモリの上限を超えた | Allowed memory size of … bytes exhausted |
PHP |
| 処理時間の上限を超えた | Maximum execution time of 2 seconds exceeded |
PHP |
| .htaccess の書き間違い | Invalid command 'RewriteEngin', perhaps misspelled … |
Apache |
| .htaccess で許されていない設定 | Options not allowed here |
Apache |
| 実行の権限が無い | (13)Permission denied: exec of '…' failed |
Apache(CGI) |
| 書き換え・内部の転送が回り続ける | rewrite or internal redirection cycle |
nginx |
| WordPress のプラグイン・テーマ・PHP の版 | There has been a critical error on this website. |
公式ドキュメント |
このほか、レンタルサーバーの事業者の解説(参考・出典に記載)では、サーバーの障害、アカウントごとの資源の制限、ディスク容量の不足も500の原因として挙げられています。ディスクが満杯になると、ログやセッションのファイルを書けずに処理が失敗します。空きは df -h で確かめます。
ずっと500(毎回出る)
プログラムの誤り・設定の誤り・権限
直前の更新・設定変更・プラグイン追加を疑う
同じ URL で必ず再現する
ときどき500(たまに出る)
負荷・メモリ・時間切れ・外部の API や DB の不調
アクセスが多い時間帯や重いページに偏る
ログの時刻と件数で傾向を見る
500エラーの原因の探し方(ログの見方)
この節では、サイトを作る人が500の原因にたどり着くまでの順番と、ログの場所・読み方が分かります。
500の理由は画面には出ず、ログに出ます。 まずアクセスログで「どの URL で、いつから、何件」を見て、次にエラーログとアプリのログで「なぜ」を見ます。
- 1再現する URL と時刻を決めるcurl -i でステータスと本文を見る。全ページか、特定のページか
- 2直前の変更を思い出すデプロイ・設定・.htaccess・プラグイン・PHP の版の変更
- 3Webサーバーの error.log を見るnginx・Apache 自身の失敗(設定・権限・ループ)はここに出る
- 4アプリのログを見る例外の名前と、自分のコードの何行目かを探す
- 5直して、200 に戻ったことを確かめる同じ curl -i をもう一度送る
ログの場所(Ubuntu の既定)
| ソフト | ログの場所・見方 | 何が分かるか |
|---|---|---|
| nginx | /var/log/nginx/error.log・access.log |
nginx 自身の失敗・どの URL が何番を返したか |
| Apache | /var/log/apache2/error.log |
.htaccess の誤り・CGI の失敗 |
| PHP | error_log で決めたファイル(無ければ SAPI のログ) |
致命的なエラーの理由と行番号 |
| Python・Node.js など | アプリの標準エラー出力(systemd なら journalctl -u サービス名) |
例外の名前とスタックトレース |
| WordPress | wp-content/debug.log(WP_DEBUG_LOG を有効にしたとき) |
プラグイン・テーマのエラー |
nginx と Apache の場所は、Ubuntu のパッケージの設定ファイル(/etc/nginx/nginx.conf の error_log /var/log/nginx/error.log;、/etc/apache2/apache2.conf の ErrorLog ${APACHE_LOG_DIR}/error.log)で確かめました。PHP の error_log について、PHP マニュアルは「設定されていない場合、エラーは SAPI のエラーロガーに送られる(Apache ならエラーログ、CLI なら stderr)」と書いています。
アクセスログで、どこで500が出ているかを数える
nginx の標準の形式(combined)では、9番目の欄がステータスコード、7番目が URL です。手元の nginx のアクセスログで、500以上を URL ごとに数えました。
# 新しい行を見続ける(Ctrl+C で終わる)
tail -f /var/log/nginx/access.log
# 5xx を URL ごとに数える
awk '$9 >= 500 {print $9, $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# error.log から error 以上の行だけを見る
grep -E "\[(error|crit|alert|emerg)\]" /var/log/nginx/error.log | tail -20
6 500 /app/orders/1/unit-price
3 500 /loop-a
1 502 /down/
1 500 /spa/about
アプリが返した500は、nginx の error.log には出ません。 上の /app/orders/1/unit-price はアクセスログに6回の500が記録されていましたが、nginx の error.log にはこの URL の行が0件でした。nginx は中継しただけで、失敗したのは奥のアプリだからです。この場合はアプリのログを見ます(次の節)。
ログを見続ける操作と絞り込みは、関連記事「tail -f・less +Fでログ監視|grep絞り込みと操作キー一覧」で扱っています。
Python(Flask)で500を起こして直す
この節では、プログラムの例外が500になる流れを、curl の応答・ログ・直したあとの200で確かめられます。
Flask では、処理していない例外が起きると、Flask が500の応答を返し、例外の内容をログに書きます。 Flask の公式ドキュメントは、例外に対応する処理が登録されていなければ汎用の「500 Internal Server Error」を返し、本番のモード(デバッグなし)では簡単なページを表示して例外をロガーに記録する、と説明しています。
わざとバグを入れた小さなアプリです。数量から2を引いて0で割ってしまい、存在しない注文番号では KeyError になります。
from flask import Flask
app = Flask(__name__)
ORDERS = {1: {"item": "ノートPC", "qty": 2, "price": 120000}}
@app.get("/ok")
def ok():
return {"status": "ok"}
@app.get("/orders/<int:order_id>/unit-price")
def unit_price(order_id):
order = ORDERS[order_id] # 無い ID だと KeyError
qty = order["qty"] - 2 # わざと入れたバグ(0 になる)
return {"unit_price": order["price"] / qty}
flask --app app run --host 127.0.0.1 --port 30301 で起動し、curl で送りました。
$ curl -i http://127.0.0.1:30301/orders/1/unit-price
HTTP/1.1 500 INTERNAL SERVER ERROR
Server: Werkzeug/3.1.8 Python/3.11.15
Content-Type: text/html; charset=utf-8
Content-Length: 265
<!doctype html>
<html lang=en>
<title>500 Internal Server Error</title>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p>
画面には理由が書かれていませんが、サーバーのログには例外の名前と行番号が出ます。 起動した端末(標準エラー出力)に出たログです(Flask の内部の行と、ファイルの場所を省いています)。
[2026-10-23 21:51:11,127] ERROR in app: Exception on /orders/1/unit-price [GET]
Traceback (most recent call last):
File ".../flask/app.py", line 1511, in wsgi_app
response = self.full_dispatch_request()
(Flask の内部の行は省略)
File ".../app.py", line 14, in unit_price
return {"unit_price": order["price"] / qty}
~~~~~~~~~~~~~~~^~~~~
ZeroDivisionError: division by zero
127.0.0.1 - - [23/Oct/2026 21:51:11] "GET /orders/1/unit-price HTTP/1.1" 500 -
スタックトレース(例外までの呼び出しの道すじ)は、いちばん下から読みます。 最後の行が例外の名前と理由、その上の File ".../app.py", line 14 が自分のコードの場所です。存在しない注文番号 9 を送ったときは、同じ形で KeyError: 9(12行目)が出ました。
直すと200に戻る
0で割る原因(数量から2を引く誤り)を消し、存在しない注文は abort(404) で「見つからない」と返すようにしました。
from flask import Flask, abort
app = Flask(__name__)
ORDERS = {1: {"item": "ノートPC", "qty": 2, "price": 120000}}
@app.get("/orders/<int:order_id>/unit-price")
def unit_price(order_id):
order = ORDERS.get(order_id)
if order is None:
abort(404) # 入力の誤りは 4xx で返す
return {"unit_price": order["price"] / order["qty"]}
$ curl -i http://127.0.0.1:30303/orders/1/unit-price
HTTP/1.1 200 OK
{"unit_price":60000.0}
$ curl -i http://127.0.0.1:30303/orders/9/unit-price
HTTP/1.1 404 NOT FOUND
<p>The requested URL was not found on the server. …</p>
存在しない番号のような「送る側の誤り」は、500ではなく 4xx(404・400 など)で返すのが筋です。 500 は「サーバー側の不具合」という意味なので、送る側は直しようがなく、監視の 5xx も増えます。例外の受け止め方は、関連記事「Python例外処理 try exceptの書き方|raise fromも実行で確認」で扱っています。
PHPで500を起こして直す(致命的なエラー・メモリ・時間切れ)
この節では、PHP の代表的な4つの500と、ログの原文、そして「画面にエラーを出す設定にすると 200 になってしまう」落とし穴が分かります。
PHP 8.4.21 の組み込みサーバーを、本番と同じく「エラーを画面に出さず、ファイルに記録する」設定(display_errors=0・log_errors=1)で起動し、メモリの上限を 16MB、処理時間の上限を2秒にしました。
php -S 127.0.0.1:30311 -d display_errors=0 -d log_errors=1 \
-d error_log=php_error.log -d memory_limit=16M -d max_execution_time=2
| 起こしたこと | 書いたコード | 応答 |
|---|---|---|
| 定義していない関数を呼ぶ | calc_total([1200, 800]); |
500(0.002秒) |
| セミコロンを忘れる | echo "こんにちは" の次の行に echo |
500(0.0004秒) |
| メモリを使い続ける | 1MB の文字列を配列に足し続ける | 500(0.007秒) |
| 終わらないループ | while (true) { $n++; } |
500(2.24秒) |
4つとも本文の無い500で、ブラウザでは「HTTP ERROR 500」の画面になりました。理由は、error_log に決めたファイルに出ています(ファイルの場所を省いています)。
[23-Oct-2026 12:52:02 UTC] PHP Fatal error: Uncaught Error: Call to undefined function calc_total() in .../fatal.php:2
Stack trace:
#0 {main}
thrown in .../fatal.php on line 2
[23-Oct-2026 12:52:02 UTC] PHP Parse error: syntax error, unexpected token "echo", expecting "," or ";" in .../parse.php on line 3
[23-Oct-2026 12:52:02 UTC] PHP Fatal error: Allowed memory size of 16777216 bytes exhausted (tried to allocate 1052672 bytes) in .../memory.php on line 4
[23-Oct-2026 12:52:05 UTC] PHP Fatal error: Maximum execution time of 2 seconds exceeded in .../timeout.php on line 3
| ログの文言 | 意味 | 直し方 |
|---|---|---|
Call to undefined function |
関数が無い(読み込み忘れ・名前の誤り・拡張機能が無い) | 関数を定義・読み込む。拡張機能なら入れる |
Parse error: syntax error |
文法の誤り。行番号は誤りの次の行を指すことがある | 指された行と、その前の行を見る |
Allowed memory size of … exhausted |
memory_limit を超えた |
一度に読み込む量を減らす。必要なら上限を上げる |
Maximum execution time of … exceeded |
max_execution_time を超えた |
処理を軽くする・分ける。必要なら上限を上げる |
直したあとの ok.php(関数を定義してから呼ぶ)は、HTTP/1.1 200 OK と 合計: 2000円 を返しました。
画面にエラーを出す設定にすると、500ではなく200になった
同じスクリプトを、display_errors=1(エラーを画面に出す)にした別のサーバーで開くと、ステータスは 200 OK になり、本文にエラーの内容とファイルの場所がそのまま表示されました。
$ curl -i http://127.0.0.1:30312/fatal.php
HTTP/1.1 200 OK
X-Powered-By: PHP/8.4.21
Content-type: text/html; charset=UTF-8
<br />
<b>Fatal error</b>: Uncaught Error: Call to undefined function calc_total() in /…/fatal.php:2
Stack trace:
#0 {main}
thrown in <b>/…/fatal.php</b> on line <b>2</b><br />
同じ致命的なエラーでも、設定で応答が変わった(PHP 8.4.21)
メモリ上限超えでも同じく、display_errors=1 では 200 になった
PHP マニュアルは display_errors について「開発を助ける機能で、本番のシステム(インターネットにつながったシステムなど)では決して使わないこと」とし、本番のサイトでは表示の代わりにログへの記録を強く勧めています。同梱の php.ini-production は display_errors を Off にしています。
nginx+アプリの500(中継・設定ミス・書き換えのループ)
この節では、nginx の後ろにアプリを置いたときに、500を誰が返しているのかの見分け方と、nginx 自身が500を返す設定ミスが分かります。
nginx 1.24.0 を自分の設定ファイルで 127.0.0.1:30321 に起動し、前の節の Flask のアプリへ中継しました。
server {
listen 127.0.0.1:30321;
root /path/to/html; # 公開するフォルダー
# アプリへ中継(アプリの 500 はそのまま通る)
location /app/ {
proxy_pass http://127.0.0.1:30301/;
}
# SPA 向けの書き方。/spa/index.html が無いと内部の転送が回り続ける
location /spa/ {
try_files $uri $uri/ /spa/index.html;
}
# 書き換えの行き来(last で互いに戻る)
location /loop-a { rewrite ^ /loop-b last; }
location /loop-b { rewrite ^ /loop-a last; }
}
500 を返すのは、奥のアプリのことも、nginx 自身のこともあります。
flowchart TD
B[ブラウザ] --> N[nginx]
N -->|中継| A[アプリ]
A -->|例外で 500| N
N -->|500 をそのまま返す| B
N -.->|設定ミス・ループ| X[nginx 自身の 500]
| 送った URL | 応答 | nginx の error.log |
|---|---|---|
/app/ok |
200 | なし |
/app/orders/1/unit-price(アプリで例外) |
500(Flask の画面がそのまま届く) | なし(アプリのログに出る) |
/spa/about(index.html が無い) |
500(nginx の画面) | rewrite or internal redirection cycle while internally redirecting to "/spa/index.html" |
/loop-a(書き換えの行き来) |
500(nginx の画面) | rewrite or internal redirection cycle while processing "/loop-b" |
/down/(止まっているアプリへ中継) |
502 | connect() failed (111: Connection refused) while connecting to upstream |
| 読む権限の無いファイル | 403(500ではない) | open() ".../secret.html" failed (13: Permission denied) |
- nginx の画面(
nginx/1.24.0 (Ubuntu)と書かれた画面)なら nginx 自身の失敗、アプリの画面ならアプリの失敗です。 見分けたら、それぞれのログを見ます。 rewrite or internal redirection cycleは、書き換えやtry_filesの行き先が見つからず、nginx の中で転送が回り続けたときの500です。 nginx の公式ドキュメントは、URI の書き換えは10回までで、locationの中でlastを使うと「10回繰り返して500のエラーを返す」と書いています(breakを使う例が示されています)。try_filesの最後の行き先のファイル(ここでは/spa/index.html)を置くと、同じ URL が 200 に戻りました。- nginx では、ファイルを読む権限が無いときは 403 になりました。 権限の誤りで500になるのは、Apache の CGI のように「プログラムを実行できない」場合です(次の節)。
設定ファイルの誤りは、反映する前に nginx -t で見つける
nginx の設定ファイルに書き間違いがあると、nginx -t(設定の検査)が失敗し、そのまま再起動すると起動できません。上の設定の server_tokens off; からセミコロンを1つ消したファイル(bad.conf)を検査したときの出力です(日時とファイルの場所の一部を省いています)。
$ nginx -t -c .../bad.conf
[emerg] invalid number of arguments in "server_tokens" directive in .../bad.conf:17
nginx: configuration file .../bad.conf test failed
$ echo $?
1
設定を変えたら、nginx -t が test is successful になってから nginx -s reload(または systemctl reload nginx)で反映します。 中継の書き方と 502・504 の対処は、関連記事「Nginxリバースプロキシ設定|proxy_passの書き方と502/504対処」で扱っています。
Apacheと.htaccessの500(書き間違い・許可・CGIの権限)
この節では、レンタルサーバーでも多い「.htaccess を書き換えたら500になった」の原因と、ログの原文・直し方が分かります。
Apache 2.4.58 を自分の設定ファイルで 127.0.0.1:30331 に起動しました(.htaccess を読む AllowOverride All と、CGI を実行する設定を入れています)。
.htaccess に1文字でも誤りがあると、そのフォルダーの下のページはすべて500になります。 RewriteEngine を RewriteEngin と書き間違えたときの応答とログです。
$ cat site/.htaccess
RewriteEngin On
RewriteRule ^old$ new.html [R=301,L]
$ curl -i http://127.0.0.1:30331/site/
HTTP/1.1 500 Internal Server Error
Server: Apache/2.4.58 (Ubuntu)
Content-Type: text/html; charset=iso-8859-1
<title>500 Internal Server Error</title>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error or
misconfiguration and was unable to complete
your request.</p>
…
<p>More information about this error may be available
in the server error log.</p>
[core:alert] [pid 13815] [client 127.0.0.1:42346] .../site/.htaccess: Invalid command 'RewriteEngin', perhaps misspelled or defined by a module not included in the server configuration
綴りを RewriteEngine に直し、RewriteBase /site/ を足すと、/site/ は 200、/site/old は 301 Moved Permanently(Location: http://127.0.0.1:30331/site/new.html)に戻りました。
| error.log の文言 | 原因 | 直し方 |
|---|---|---|
Invalid command '…', perhaps misspelled or defined by a module not included … |
綴りの誤り、またはそのモジュール(mod_rewrite 等)が読み込まれていない | 綴りを直す。モジュールを有効にする |
Options not allowed here |
AllowOverride で許していない設定を書いた |
その行を消すか、サーバーの設定で許可する |
(13)Permission denied: exec of '…' failed |
CGI のファイルに実行の権限が無い | chmod 755 で実行できるようにする |
End of script output before headers |
CGI がヘッダーを出す前に終わった(エラーで終了など) | 直前の行に出たプログラムのエラーを見る |
malformed header from script '…': Bad header: … |
CGI が Content-Type: などのヘッダーを出さずに本文を出した |
先頭にヘッダーと空行を出す |
Options not allowed here は、AllowOverride FileInfo のフォルダーに Options -Indexes を書いて起こしました。Apache の公式ドキュメントは、.htaccess で使える設定は AllowOverride で決まり、既定値は None(.htaccess を読まない)だと説明しています。また、.htaccess に意味の無い語を書いて500にならなければ、そのファイルは読まれていない、という確かめ方も載せています。
実行の権限が無い CGI は500になり、chmod 755 で 200 に戻りました。 権限の数字の意味は、関連記事「chmodの755と644の意味|用途別パーミッション早見表」で扱っています。
- 1書き換える前に .htaccess を別名で保存しておく500になったら元のファイルに戻すだけで直る
- 2500になったら、まず .htaccess を外して試すWordPress の公式ドキュメントも .htaccess_old に名前を変える方法を最初に挙げている
- 3サーバーの設定を変えられるなら apachectl configtestSyntax OK を見てから反映する(手元では apache2 -t で Syntax OK を確認)
- 4error.log の .htaccess のパスと文言を読むどのフォルダーの、どの設定かが書かれている
WordPressで500エラーが出たとき
この節では、WordPress のサイトで500や「重大なエラー」が出たときの、公式の切り分けの順番が分かります。
WordPress の公式ドキュメントは、Internal Server Error の切り分けとして、.htaccess → プラグイン → テーマ → PHP のメモリの上限 → コアのファイル、の順を挙げています。
.htaccess を外して試す
FTP などで .htaccess を .htaccess_old に名前を変えて再読み込みする。直ったら「設定」>「パーマリンク」で保存し直して .htaccess を作り直す。
プラグインをすべて止める
管理画面に入れないときは、wp-content の plugins フォルダーを plugins.hold などに名前を変えると、すべてのプラグインが止まる。1つずつ戻して原因を探す。
標準のテーマに切り替える
Twenty Twenty-One などの標準テーマにして、テーマが原因かを確かめる。
PHP のメモリの上限を上げる
wp-config.php の WP_MEMORY_LIMIT で上限を指定する。既定では 40MB(マルチサイトは 64MB)まで上げようとする。
wp-admin と wp-includes を入れ直す
WordPress の新しいファイル一式から、2つのフォルダーをアップロードし直す。
「このサイトで重大なエラーが発生しました」(There has been a critical error on this website.)も、ステータスは500です。 WordPress のソースコード(class-wp-fatal-error-handler.php)では、致命的なエラーを受け止めたときに、この文言の画面を 'response' => 500 で返しています。WordPress の公式ドキュメントによると、WordPress 5.2 で「リカバリーモード」が入り、プラグインが致命的なエラーを起こしたときに、真っ白な画面ではなくメッセージを表示するようになりました。画面に「Please check your site admin email inbox for instructions.」(サイト管理者のメールを確認するように)と出たときは、管理者のメールを見ます。
原因を調べるときは、wp-config.php でログをファイルに書く設定にします。WordPress の公式ドキュメントの書き方です。
// エラーをログに書く(wp-content/debug.log)
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
// エラーを画面に出さない
define( 'WP_DEBUG_DISPLAY', false );
// メモリの上限を 64MB にする例
define( 'WP_MEMORY_LIMIT', '64M' );
- 公式ドキュメントは、
WP_DEBUGなどのデバッグの道具を、公開中のサイトで使うことは勧めないとしています。原因が分かったらfalseに戻します。 - 重大なエラーの原因として、公式ドキュメントはプラグインの競合、テーマの互換性、PHP の版が合わない、メモリの上限、壊れたファイルを挙げています。PHP の版を上げた直後に500になった場合は、プラグインやテーマがその版に対応しているかを確かめます。
本番で詳しいエラーを外に出さない設定
この節では、500の理由を見ている人に見せず、ログにだけ残すための設定を、ソフトごとに確かめられます。
エラーの詳しい内容(スタックトレース・ファイルの場所・ソフトの版)は、見ている人には役に立たず、サーバーの中の情報を外に知らせることになります。 画面には短い案内とお問い合わせ番号だけを出し、詳しい内容はログに残します。
Flask をデバッグモード(flask run --debug)で動かして同じ500を起こすと、応答の本文は 13,952 バイトになり、例外の名前、ソースコードの行、サーバー上のファイルの場所(3か所)、ブラウザから Python を実行できるコンソールの部品が含まれていました。Flask の公式ドキュメントは、デバッガーはブラウザから任意の Python のコードを実行できるとし、「本番の環境で開発用サーバーやデバッガーを動かさないこと」と書いています。
| ソフト | 本番の設定 | 手元で確かめた結果 |
|---|---|---|
| Flask | デバッグモードにしない。@app.errorhandler(500) で自分の画面 |
案内と番号だけの500。理由はログへ |
| PHP | display_errors = Off・log_errors = On・error_log |
本文なしの500。理由は error_log へ |
| nginx | error_page 500 502 503 504 /50x.html;・server_tokens off; |
自作の画面。Server: nginx(版なし) |
| Apache | ErrorDocument 500 /errors/500.html・ServerTokens Prod |
自作の画面。Server: Apache(版なし) |
| WordPress | WP_DEBUG_DISPLAY を false(WP_DEBUG は調べるときだけ) |
公式ドキュメントで確認 |
Flask:自分の500の画面と、ログを結ぶお問い合わせ番号
Flask の公式ドキュメントの方法で500の処理を登録し、リクエストごとに番号を付けて、画面とログの両方に出しました。e.original_exception で元の例外を取り出せます。
import logging, uuid
from flask import Flask, g, request
app = Flask(__name__)
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
@app.before_request
def set_request_id():
g.request_id = uuid.uuid4().hex[:8] # 問い合わせとログを結ぶ番号
@app.errorhandler(500)
def internal_error(e):
# 詳しい内容(e.original_exception)はログにだけ書く
app.logger.error("request_id=%s path=%s error=%r",
g.request_id, request.path, e.original_exception)
body = ("<h1>ただいま表示できません</h1>"
f"<p>お問い合わせ番号:{g.request_id}</p>")
return body, 500, {"Cache-Control": "no-store"}
$ curl -i http://127.0.0.1:30304/orders/1/unit-price
HTTP/1.1 500 INTERNAL SERVER ERROR
Cache-Control: no-store
Content-Type: text/html; charset=utf-8
Content-Length: 84
<h1>ただいま表示できません</h1><p>お問い合わせ番号:bdb0b414</p>
(サーバーのログ)
2026-10-23 21:51:49,521 ERROR request_id=bdb0b414 path=/orders/1/unit-price error=ZeroDivisionError('division by zero')
見ている人から「お問い合わせ番号 bdb0b414」と連絡があれば、ログをその番号で探すと原因の行にたどり着けます。MDN の500の例も、本文にリクエスト ID を入れてログと照らし合わせる形を示しています。Flask の公式ドキュメントによると、デバッグモードではこの500の処理は使われず、デバッガーの画面になります。
nginx・Apache:自分のエラーページと、版を出さない設定
nginx に error_page と proxy_intercept_errors on;(アプリが返した500も差し替える)を足すと、アプリの500でも自作のページが返り、Server ヘッダーから版が消えました。
server_tokens off; # 版を出さない
error_page 500 502 503 504 /50x.html; # 自分で用意したページを返す
location = /50x.html { internal; }
location /app/ {
proxy_pass http://127.0.0.1:30301/;
proxy_intercept_errors on; # アプリの 500 も差し替える
}
$ curl -i http://127.0.0.1:30321/app/orders/1/unit-price
HTTP/1.1 500 Internal Server Error
Server: nginx
Content-Type: text/html
<h1>ただいま表示できません</h1><p>時間をおいて再度お試しください。</p>
ただし、書き換えのループ(/loop-a)の500には、error_page の自作ページが使われず、nginx の標準の画面が返りました。 転送の回数が上限に達したあとなので、エラーページへの転送もできないためです。ループの500は、設定を直すしかありません。
Apache は ErrorDocument 500 /errors/500.html と ServerTokens Prod を足すと、CGI の500でも自作の画面が返り、Server: Apache になりました。
500と502・503・504の違い
この節では、500と、似た番号の 502・503・504 の違いと、手元で同じ中継から返ったコードの違いが分かります。
500 は主にアプリやサーバー自身が「中で失敗した」と返す番号で、502・503・504 は主に中継役や受け付け側が「奥がおかしい・今は無理・待ちきれない」と返す番号です。
| コード | 何が起きたか | よくある原因 |
|---|---|---|
| 500 | サーバーの中で想定外のエラー | 例外・設定の誤り・権限・メモリ・時間切れ |
| 502 Bad Gateway | 中継役が奥から不正な応答を受けた・接続を断られた | アプリが止まっている・ポート違い |
| 503 Service Unavailable | 今はリクエストを受け付けられない | メンテナンス中・過負荷 |
| 504 Gateway Timeout | 中継役が奥の返事を待ちきれなかった | 処理が遅い・DB や外部 API が遅い |
手元の nginx では、同じ「アプリへの中継」でも、アプリが動いていて例外を起こしたときは 500(アプリの応答がそのまま届く)、アプリが止まっていたときは 502(connect() failed (111: Connection refused))でした。
502・503・504 を nginx で起こした実例と直し方は、関連記事「504 Gateway Time-outの原因と直し方|502・503との違いと実例」で扱っています。
500エラーはSEO(検索順位)に影響するか
この節では、500が続いたときに Google の検索でどう扱われるのかが分かります。
短い時間の500ですぐにページが消えることはありませんが、続くとクロールが遅くなり、最終的には検索の索引から外れます。 Google 検索セントラルの「HTTP ステータスコード、ネットワーク エラー、DNS エラーが Google 検索に与える影響」(2026年2月4日更新)は、次のように書いています。
- 5xx と 429 のエラーを受けると、Google のクローラーはクロールを一時的に遅くする。
- すでにインデックスに登録された URL はしばらく保たれるが、最終的には削除される。
- 500 では、クロールの速度を下げる度合いは、サーバーエラーを返している URL の数に比例する。
- サーバーが 2xx を返すようになると、クロールの速度は少しずつ戻る。
- 5xx を返した URL から受け取った内容は使われない。
計画したメンテナンスで一時的に止めるときは、500ではなく 503 を返します。 503 の返し方と Retry-After は、関連記事「504 Gateway Time-outの原因と直し方|502・503との違いと実例」で扱っています。
500エラーを減らす・早く気づくための準備
この節では、500を出しにくくし、出たときに早く気づいて直すための準備が分かります。
- 1設定を反映する前に検査するnginx -t・apachectl configtest・php -l(PHP の文法の検査。手元の parse.php では Errors parsing parse.php と出た)
- 2変更の前にバックアップを取る.htaccess・設定ファイル・プラグインの更新の前に、すぐ戻せる形にする
- 35xx の件数と割合を監視するアクセスログの5xxを数え、増えたら知らせる
- 4エラーを記録する仕組みを入れるFlask の公式ドキュメントは Sentry などのエラー追跡を例に挙げている
- 5入力の誤りは 4xx で返す想定できる失敗を500にしないと、本当の不具合が目立つ
- 6ディスクとメモリの空きを見るdf -h・free -h。ログが増え続けていないか
よくある質問
Q. 500エラーとは何ですか? A. 「500 Internal Server Error(内部サーバーエラー)」のことで、サイトのサーバー側で想定外の問題が起き、ページを返せなかったという意味です。見ている人の端末ではなく、サイト側で直すエラーです。
Q. 500エラーは自分だけに出ているのですか? A. 多くはサイト側の問題なので、ほかの人にも出ています。別の端末や別の回線で同じ URL を開いて、同じ500が出ればサイト側の問題です。
Q. 500エラーはいつ直りますか? A. 一時的な負荷や更新作業なら数分で直ることがありますが、プログラムや設定の誤りはサイト側が直すまで続きます。長く続くときは、日時と URL を添えて運営者に知らせます。
Q. Chrome で「このページは動作していません」「HTTP ERROR 500」と出ます。 A. サーバーが本文の無い500を返したときに、Chrome が代わりに出す画面です。手元の PHP で、エラーを画面に出さない設定のまま致命的なエラーを起こすと、この画面になりました。
Q. スマホで500エラーが出ます。スマホの設定の問題ですか? A. 500 はサーバー側のエラーなので、スマホの設定を変えても直りません。時間をおいて再読み込みし、直らなければサイトの運営者に知らせます。
Q. 500エラーの直し方は(サイトを作る側)?
A. エラーログとアプリのログで理由を見て、その原因を直します。直前の更新・設定変更を戻すと直ることが多く、直したら同じ URL に curl -i を送って 200 に戻ったことを確かめます。
Q. WordPress で500エラーが出ました。
A. 公式ドキュメントの順に、.htaccess を外す → プラグインをすべて止める → 標準のテーマにする → メモリの上限を上げる → wp-admin と wp-includes を入れ直す、で切り分けます。原因は WP_DEBUG_LOG で wp-content/debug.log に書き出して確かめます。
Q. .htaccess を書き換えたら500になりました。
A. 綴りの誤り、読み込まれていないモジュールの設定、AllowOverride で許されていない設定のどれかが多い原因です。保存しておいた元の .htaccess に戻すと直り、Apache の error.log に誤りの行の文言が出ます。
Q. 500エラーは SEO に影響しますか? A. 続くと Google のクロールが遅くなり、最終的にはインデックスから外れます(Google 検索セントラル)。メンテナンスで止めるときは 503 を返します。
Q. 500と503の違いは? A. 500 はサーバーの中で想定外のエラーが起きたこと、503 は今はリクエストを受け付けられない(メンテナンス中・過負荷)ことを示します。計画した停止には 503 を使います。
Q. 入力の誤りに500を返してもよいですか?
A. 500 は「サーバー側の不具合」という意味なので、送る側の誤り(存在しない ID・必須項目が空など)には 400・404 などの 4xx を返すのが筋です。手元の Flask でも、存在しない注文番号は abort(404) で 404 にしました。
まとめ
- 500エラー(500 Internal Server Error)は、サーバーの中で想定外の問題が起き、ページを返せなかったという意味。直すのはサイト側。
- 見ている人は、数分おいて再読み込み → ほかのページ → 公式のお知らせ → 日時と URL を添えて連絡。送信の直後なら、履歴を見てから操作し直す。
- サイトを作る人は、アクセスログで「どこで・いつから」、error.log とアプリのログで「なぜ」を見る。アプリが返した500は nginx の error.log には出なかった。
- 手元では、Flask の例外、PHP の未定義の関数・文法・メモリ・時間切れ、nginx の書き換えのループ、Apache の .htaccess の誤りと CGI の権限で500になり、原因を直すと 200 に戻った。
- PHP は
display_errors=1にすると、致命的なエラーでも 200 になり、ファイルの場所が画面に出た。本番は表示を止めてログに残す。 - 502・503・504 は主に中継役が返す番号。メンテナンスで止めるときは 503 を返す。
次に読むとよい記事です。502・503・504 の実例は関連記事「504 Gateway Time-outの原因と直し方|502・503との違いと実例」で、ほかのステータスコードは関連記事「HTTPステータスコード 一覧|全コードの原因と対処・curl実例つき」で扱っています。
参考・出典
確認日はいずれも 2026年10月23日です。
- MDN「500 Internal Server Error」:https://developer.mozilla.org/ja/docs/Web/HTTP/Reference/Status/500
- MDN「HTTP レスポンスステータスコード」:https://developer.mozilla.org/ja/docs/Web/HTTP/Reference/Status
- IETF「RFC 9110 HTTP Semantics」15.6 Server Error 5xx:https://www.rfc-editor.org/rfc/rfc9110#section-15.6
- Flask「Handling Application Errors」:https://flask.palletsprojects.com/en/stable/errorhandling/
- Flask「Debugging Application Errors」:https://flask.palletsprojects.com/en/stable/debugging/
- PHP マニュアル「実行時設定(エラー処理)」:https://www.php.net/manual/en/errorfunc.configuration.php
- nginx「Module ngx_http_rewrite_module」:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html
- Apache HTTP Server「Apache HTTP Server Tutorial: .htaccess files」:https://httpd.apache.org/docs/2.4/howto/htaccess.html
- WordPress「Common WordPress Errors」:https://developer.wordpress.org/advanced-administration/wordpress/common-errors/
- WordPress「Debugging in WordPress」:https://developer.wordpress.org/advanced-administration/debug/debug-wordpress/
- WordPress「Editing wp-config.php」:https://developer.wordpress.org/advanced-administration/wordpress/wp-config/
- WordPress のソースコード「class-wp-fatal-error-handler.php」:https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/class-wp-fatal-error-handler.php
- Google 検索セントラル「HTTP ステータスコード、ネットワーク エラー、DNS エラーが Google 検索に与える影響」:https://developers.google.com/search/docs/crawling-indexing/http-network-errors
- エックスサーバー「500 Internal Server Errorとは?エラーの原因と対処法を分かりやすく解説」:https://www.xserver.ne.jp/bizhp/500-internal-server-error/
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「500エラーとは|Internal Server Errorの原因と直し方を実例で」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。