【解決録】Neon × Render × Rails デプロイで relation "users" already exists が出たとき
Rails アプリを Render + Neon(PostgreSQL) にデプロイしたとき、
PG::DuplicateTable: ERROR: relation “users” already exists
という “テーブル重複エラー” にハマりました。
以下のような状況で発生しました:
• もともと Rails で手動作成した User モデルが存在していた
• その後 Devise を導入して devise_create_users を生成した
• ローカルでは問題なし
• Render(本番)へデプロイすると Users テーブルがすでに存在するよとエラーが出る
最終的に Neon 側のテーブル状態と Render の migrate がズレていたことが原因で、
正しくDBをリセットすることで解決しました。
この記事ではその流れを 実際のエラー → 解決策 → 学べたこと の順にまとめます。
発生したエラー
デプロイすると以下のようなログが Render 側で発生。
PG::DuplicateTable: ERROR: relation "users" already exists /opt/render/project/src/db/migrate/20251210040000_devise_create_users.rb:5:in change'
Render の migrate は途中でストップし、アプリはデプロイ失敗。
ローカル(development)は正常なのに、本番(Neon)だけ壊れるパターン。
原因
• Neon の本番DBには過去に作った users テーブルがすでに存在していた
• しかし Rails の schema_migrations テーブルはズレており「まだ migrate していない扱い」
• Devise の create_table :users が “すでにあるテーブル” に対して再実行されてしまう
つまり、
Neon(本番)とローカルのDB状態がズレていた
これがすべての原因でした。
解決した方法
① Neon の SQL Editor を開く
Neon の Web コンソール → SQL Editor を開きます。
② 全テーブルを drop(または users だけ drop)
今回私は全部リセットする方を選んだのでこちらを実行:
DROP SCHEMA public CASCADE;
CREATE SCHEMA public;
③ デプロイを再実行 → 無事成功 🎉
Neon と Rails の状態が揃い、 migrate が正しく実行されてデプロイ成功しました。
なぜローカルは動いて、本番だけ壊れた?
• ローカルは rails db:migrate:reset などで綺麗にしていた
• 本番(Neon)は昔の users テーブルが残ったままだった
• schema_migrations の migrate 状態もズレていた
という “環境差異問題” です。
デプロイ先の DB 状態は、古い情報が残ります。
今回学べたこと
✔ 本番DB(Neon)はローカルと同じ状態と思い込むな
データベースのズレはデプロイ失敗の典型的なパターン(みたい)。
✔ Devise 導入前後で User テーブルを作り直した場合は特に注意
名前が同じなので conflict が非常に起きやすい。
✔ Neon の SQL Editor でテーブルを直接確認できるのは超便利
Rails ではなく DB 側を疑うクセをつけると早い。
まとめ
付録:今回の実行コマンド(ローカル)
docker compose exec web rails db:migrate:status
確認結果:
up Devise create users
up Add fields to users
up Create challenges
up Create participations
up Create wake up logs
ローカルでは全て up だが、本番は違う状態だったためエラー発生。
最終的に、
Neon 側のテーブルを drop → 通常 migrate → デプロイ成功
という流れで解決できました。
Discussion