ERROR: current transaction is aborted, commands ignored until end of transaction block は、同じトランザクションの中で、すでに別のエラーが起きているときに出るエラーです。 PostgreSQL は、トランザクションの中で1つでもエラーが起きると、そのトランザクションを「失敗した状態」にし、ROLLBACK するまでほかの SQL をすべて受け付けません。

このエラーそのものは原因ではありません。本当の原因は、その前に出たエラーです。

手順 やること
1 このエラーより前に出たエラー(ログ・例外)を探す。それが本当の原因
2 失敗したトランザクションを ROLLBACK する
3 1件の失敗で全体を止めたくないなら、SAVEPOINT を使う

確認環境:PostgreSQL 16.15、psql、Python 3.11(psycopg 3.3.6)、Java 21(PostgreSQL JDBC 42.7.2)、比較に MySQL 8.0.46(確認日 2026年10月11日)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「current transaction is abortedの原因と直し方」

再現:psql で、途中の INSERT が失敗する

txdemo=> BEGIN;
BEGIN
txdemo=> INSERT INTO item VALUES (1, 'ぶどう', 300);          ← id=1 はすでにある
ERROR:  duplicate key value violates unique constraint "item_pkey"
DETAIL:  Key (id)=(1) already exists.
txdemo=> SELECT 1;                                              ← 何を実行しても
ERROR:  current transaction is aborted, commands ignored until end of transaction block
txdemo=> COMMIT;
ROLLBACK                                                        ← COMMIT が ROLLBACK になった

最初の duplicate key が本当の原因で、そのあとの SQL は、SELECT 1 のような何の問題もない SQL でもすべてこのエラーになります。COMMIT を実行すると、応答が ROLLBACK になり、トランザクションの中で成功していた INSERT も含めて、すべて取り消されました。

本当の原因の探し方

方法 内容
アプリのログで、このエラーの直前の例外を探す 例外を catch してログを出さずに続けていると、最初のエラーが見つからない
PostgreSQL のサーバーのログ 最初のエラーの SQL と内容が残る(ERROR: duplicate key ...)
pg_stat_activity の state 失敗したまま止まっている接続は idle in transaction (aborted)
SELECT pid, state, left(query, 40) FROM pg_stat_activity WHERE usename = 'tx';
-- idle in transaction (aborted) | INSERT INTO item VALUES ($1, $2, 100)

query の列には、その接続が最後に実行した SQLが出ます。失敗の原因になった SQL の手がかりになります。

危険:例外を握りつぶすと、commit が成功に見えて何も保存されない

アプリで、エラーをログに出さずに処理を続けると、もっと見つけにくい形になりました。

Python(psycopg)

for i, name in [(6, "a"), (1, "dup"), (7, "b")]:
    try:
        cur.execute("INSERT INTO item VALUES (%s, %s, 100)", (i, name))
    except psycopg.Error as e:
        print("握りつぶした:", type(e).__name__)
conn.commit()
握りつぶした: UniqueViolation              ← id=1 の本当のエラー
握りつぶした: InFailedSqlTransaction       ← id=7 はこのエラーで入らなかった
commit: ok                                 ← 例外にならない
id 6,7 の件数: 0                           ← 成功したはずの id=6 も保存されていない

Java(JDBC)

id=6: ok
id=1: 23505 ERROR: duplicate key value violates unique constraint "item_pkey"
id=7: 25P02 ERROR: current transaction is aborted, commands ignored until end of transaction block
commit: ok                                 ← 例外にならない
(保存された件数)0

Python も Java も、commit() は例外を出さずに終わり、実際には何も保存されていませんでした。 確認環境の psycopg 3.3.6 と PostgreSQL JDBC 42.7.2 では、どちらも同じ結果です。「エラーの行だけ飛ばして、残りは保存されたはず」と思い込みやすく、データが黙って消える形の不具合になります。

MySQL では動きが違う

同じ処理を MySQL(PyMySQL)で実行すると、id=1 だけが 1062(重複)で失敗し、id=6 と id=7 は保存されました。MySQL では、トランザクションの中でエラーになった文だけが失敗し、続きの SQL は実行できます。MySQL から PostgreSQL に移したアプリで、このエラーに初めて出会うことがよくあります。

直し方1:エラーが起きたら ROLLBACK して、やり直す

1件でも失敗したら全体を取り消してよい処理(振り込み・注文の確定など)は、エラーを受け取ったら ROLLBACK し、例外を呼び出し元に伝えます。握りつぶさないことが一番の対策です。

try:
    with conn.transaction():          # 例外が起きたら自動で ROLLBACK
        cur.execute(...)
        cur.execute(...)
except psycopg.Error:
    logger.exception("登録に失敗")     # 最初のエラーを必ずログに残す
    raise

直し方2:1件ずつ SAVEPOINT(失敗した行だけ飛ばす)

取り込みのように、失敗した行だけ飛ばして残りは保存したいときは、1件ごとに SAVEPOINT を置き、失敗したらその地点まで戻します(PostgreSQL 公式ドキュメントの SAVEPOINT の使い方)。

SQL(psql)

BEGIN;
INSERT INTO item VALUES (4, 'なし', 120);
SAVEPOINT sp1;
INSERT INTO item VALUES (1, 'ぶどう', 300);     -- 失敗
ROLLBACK TO SAVEPOINT sp1;                     -- この1件だけ取り消す
INSERT INTO item VALUES (5, 'かき', 150);
COMMIT;                                        -- 4 と 5 が保存された

Python(psycopg 3)

with conn.transaction():
    for i, name in rows:
        try:
            with conn.transaction():          # 入れ子にすると SAVEPOINT になる
                cur.execute("INSERT INTO item VALUES (%s, %s, 100)", (i, name))
        except psycopg.errors.UniqueViolation as e:
            print(f"id={i}: スキップ({e.diag.message_detail})")
id=6: ok
id=1: スキップ(Key (id)=(1) already exists.)
id=7: ok
保存された: [(6,), (7,)]

Java(JDBC)

for (int id : ids) {
    Savepoint sp = con.setSavepoint();
    try (PreparedStatement ps = con.prepareStatement("INSERT INTO item VALUES (?, 'x', 100)")) {
        ps.setInt(1, id);
        ps.executeUpdate();
        con.releaseSavepoint(sp);
    } catch (SQLException e) {
        con.rollback(sp);                 // この1件だけ取り消す
        log.warn("id=" + id + " をスキップ: " + e.getSQLState());
    }
}
con.commit();                             // 6 と 7 が保存された

PostgreSQL JDBC には、接続 URL に autosave=always を付けると、SQL ごとに自動で SAVEPOINT を置く設定もあります。確認環境でも、付けると id=6・7 が保存されました。ただし、すべての SQL に SAVEPOINT が増えるので、必要な処理に絞って使います。

psql で作業するとき:ON_ERROR_ROLLBACK

psql で手作業をしていて、打ち間違い1つでトランザクション全体が止まるのを避けたいときは、次の設定が便利です。

\set ON_ERROR_ROLLBACK interactive
BEGIN;
INSERT INTO item VALUES (2, 'みかん', 80);   -- INSERT 0 1
INSERT INTO item VALUES (1, 'ぶどう', 300);  -- ERROR: duplicate key ...(この文だけ取り消し)
INSERT INTO item VALUES (3, 'もも', 250);    -- INSERT 0 1(続けられる)
COMMIT;                                       -- COMMIT(2 と 3 が保存された)

interactive にすると、手で打っているときだけ有効になります。確認環境でも、同じ SQL をファイルから流し込んだときは有効にならず、通常どおり current transaction is aborted で止まり、COMMIT は ROLLBACK になりました。スクリプトでは、エラーで止まるほうが安全です。上の例は \set ON_ERROR_ROLLBACK on で確かめた結果です。

確認の手順(チェックリスト)

順番 確認すること 方法
1 直前のエラー アプリのログ・サーバーのログで、このエラーの前の ERROR を探す
2 例外を握りつぶしていないか except: pass・catch でログを出さずに続けている箇所
3 commit で本当に保存されたか 件数を数えて確かめる(commit は成功に見える)
4 全体を取り消す処理か 取り消すなら ROLLBACK して例外を伝える
5 失敗した行だけ飛ばす処理か SAVEPOINT(psycopg は conn.transaction() の入れ子、JDBC は setSavepoint)
6 止まっている接続 pg_stat_activity の idle in transaction (aborted)

よくある質問

Q. 自動コミット(autocommit)にすれば出ませんか。 A. 出なくなります。1文ごとに確定するので、失敗した文だけが失敗します。ただし、複数の更新をまとめて取り消すことはできなくなるため、まとめて成功・失敗させたい処理には使いません。

Q. SQLSTATE は何ですか。 A. このエラーは 25P02 です。Java では getSQLState()、psycopg では InFailedSqlTransaction の例外として受け取れます。この SQLSTATE を見たら、ログをさかのぼって最初のエラーを探す、と覚えておきます。

まとめ

  • トランザクションの中で先にエラーが起きると、以降の SQL はすべてこのエラー。本当の原因は直前のエラー
  • psql の COMMIT は ROLLBACK になる。成功していた更新も消える
  • Python(psycopg)と Java(JDBC)では commit が例外にならず、何も保存されなかった。握りつぶしは危険
  • MySQL はエラーの文だけ失敗する。MySQL から移したアプリで出会いやすい
  • 全体を取り消すなら ROLLBACK して例外を伝える、行だけ飛ばすなら SAVEPOINT
  • 手作業の psql は \set ON_ERROR_ROLLBACK interactive

参考・出典

確認日はいずれも 2026年10月11日です。

  • PostgreSQL 16 Documentation「SAVEPOINT」:https://www.postgresql.org/docs/16/sql-savepoint.html

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「current transaction is abortedの原因と直し方」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?