PostgreSQL への接続が認証タイプ 10 で落ちたので pgjdbc を「SCRAM 対応版」に上げた——その直後に、 今度は別の例外で止まります。
java.lang.NoClassDefFoundError: org/postgresql/shaded/com/ongres/scram/client/ScramClient$ChannelBinding
Caused by: java.lang.ClassNotFoundException: org.postgresql.shaded.com.ongres.scram.client.ScramClient$ChannelBinding
落ちているのは pgjdbc が SCRAM の認証交渉を始めた地点で、参照しているクラスは pgjdbc が自分の jar の中へ 取り込んだはずのものです。
直し方の要点を先に
pgjdbc を上げます。 pom.xml の既存の org.postgresql:postgresql の <version> を、公式が案内している
現行の保守版に更新します。
<!-- pom.xml の既存の依存の version を更新する -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.13</version>
</dependency>
この同梱漏れが直った最初の版は 42.2.1 です。実測でも、classpath に置く jar の版だけを 42.2.0 から
42.2.1 に替えたところ、同じサーバ・同じ URL・同じユーザー・同じ接続コードで接続が成功しました。
ただし 42.2.1 は 2018 年の版で、固定する先ではありません。
このエラーを踏んだ人ほど、上げ先を新しくする理由があります。 pgjdbc は SCRAM 認証まわりで High 深刻度の
脆弱性を複数修正しています——channelBinding=require のフォールバック(CVE-2025-49146・42.7.7 で修正)、
SCRAM の PBKDF2 反復回数が無制限で CPU を枯渇させる問題(CVE-2026-42198・42.7.11 で修正)、
チャネルバインディングの静かな格下げ(CVE-2026-54291・42.7.12 で修正)。いま直そうとしているのと同じ
SCRAM 経路の修正なので、42.2.1 で止めるとそれらを全部残すことになります。
Gradle や、親 POM・BOM で版を管理している構成では、そちらの宣言を更新します。
com.ongres.scram:client を依存に足しても解決しません。 足りていないクラスの名前は
org.postgresql.shaded.com.ongres.scram.client.ScramClient で、org.postgresql.shaded. が付いています。
これは pgjdbc が自分の jar の中へ取り込むときに付け替えた名前で、上流の com.ongres.scram:client が
公開しているのは com.ongres.scram.client.ScramClient(接頭辞なし)です。実測でも、42.2.0 の隣に
com.ongres.scram:client / common と stringprep を classpath へ置いて接続したところ、同じ
NoClassDefFoundError が同じ場所から返りました(ScramAuthenticator.processServerMechanismsAndInit)。
埋まる場所は pgjdbc の jar の中だけです。
なぜ 42.2.0 で出るのか:jar に SCRAM の client パッケージだけが入っていない
pgjdbc 42.2.0 は SCRAM-SHA-256 対応を入れた最初の版ですが、その実装の一部が jar に同梱されないまま
リリースされました。 上流の CHANGELOG は、42.2.0 の Known issues にこう書いています。
SCRAM does not work as scram:client library is not packaged
そして 42.2.1 の Fixed に修正が入ります。
Package scram:client classes, so SCRAM works when using a shaded jar
実際に Maven Central の jar を取得して中身を数えると、境界は 1 つのパッケージの有無に出ます。
| 版 | org/postgresql/shaded/com/ongres/scram/ 配下のエントリ | .../scram/client/ パッケージ |
|---|---|---|
| 42.1.4 | 0 | 無し(SCRAM 自体が未対応) |
| 42.2.0 | 39 | 無し |
| 42.2.1 | 50 | あり |
| 42.7.4 | 51 | あり |
42.2.0 には scram/common(exception / gssapi / message / stringprep / util)は入っていて、
scram/client だけがありません。認証交渉を始めるところまでは進み、クライアント側の実装を呼ぶ地点で
落ちます。 42.2.1 で増えているパッケージは org/postgresql/shaded/com/ongres/scram/client の 1 つだけです。
依存として補える性質のものでもありません。42.2.0 と 42.2.1 の POM を見ると、どちらにも SCRAM ライブラリの 実行時依存は宣言されていません(宣言されているのは test スコープと provided/optional の OSGi だけ)。 この 2 つの版の差は、宣言された依存ではなく jar の中身にあります。
開けて数えたのは上の 4 つの版だけです。42.2.2 から 42.7.3 までの中間版は確認していません。この表が言えるのは 「42.2.1 が同梱を直した最初の版」と「42.7.4 にも入っている」の 2 点で、そこから「中間版ならどれでもよい」は 出てきません(上げ先は直し方の節のとおり現行の保守版にします)。
42.2.0 は「SCRAM 対応版」として案内されている
SCRAM 対応が入ったのが 42.2.0 なので、対処を案内する文書では「pgjdbc 42.2.0 以降」という下限がよく使われます。
この下限は「SCRAM のコードが入った最初の版」としては正しく、同梱漏れが直った版としては 1 つ手前です。
下限どおり 42.2.0 を選ぶと、1 段目のエラー(The authentication type 10 is not supported)は消えて、
このページのエラーに変わります。
1 段目のほう、つまりまだ authentication type 10 で止まっている場合は
The authentication type 10 is not supported の直し方
を参照してください。**症状は違いますが、直すのは同じ 1 箇所(pgjdbc の版)**で、行き先を現行の保守版にすれば
2 段とも越えます。
切り分け
ClassNotFoundExceptionのクラス名にshadedが入っていない(com.ongres.scram.client.ScramClientなど): それは pgjdbc の同梱版ではなく、外部の SCRAM ライブラリを直接参照している構成です。この記事の境界とは 別の経路なので、その依存の解決状況を確認します。本記事では実測していません。- 依存を上げたのに同じ例外が出る:実行時に読まれている jar が別のものである可能性があります。
アプリケーションサーバの
lib/や、シェーディングして固めた fat jar の中に古い pgjdbc が残っていると、 依存の宣言よりそちらが優先されることがあります。 NoSuchMethodErrorや別のクラスで落ちる:同じ jar の中に 2 つの版の pgjdbc が混ざっている構成で起きます。mvn dependency:treeでorg.postgresql:postgresqlが 1 つに解決されているかを確認します。- サーバ側を
md5に戻せば動く:SCRAM の交渉自体が起きなくなるので、この例外も出なくなります。 ただし PostgreSQL 18 のドキュメントは md5 を非推奨・将来削除と案内しています(1 段目の記事に版ごとの 書かれ方をまとめてあります)。また、上に挙げた SCRAM 関連の修正もドライバ側にあるので、 ドライバの版を動かすほうが 1 箇所で済みます。
検証環境
- image:
postgres(digest 固定sha256:33f923b0...= PostgreSQL 16.14)。同じコンテナにdefault-jdk-headlessを追加し、PostgreSQL サーバと JDBC クライアントを 1 コンテナ内で動かして127.0.0.1へ接続 - 公式
postgresイメージは127.0.0.1からの接続をtrust(認証なし)にしているため、pg_hba.confの 該当行をscram-sha-256に戻してから検証している(イメージ固有の緩和を外して認証交渉を起こすため) - 再現:
postgresql-42.2.0.jarを classpath に置いて接続 → 上記のNoClassDefFoundError・終了コード 1 - 修正:
postgresql-42.2.1.jarに替えて同じ接続 →SELECT 1まで通って終了コード 0 - reproduce と fix で違うのは classpath の jar 1 つだけ。サーバ・URL・ユーザー・接続コードは同一
- jar の中身の表は、Maven Central から 42.1.4 / 42.2.0 / 42.2.1 / 42.7.4 の jar を取得し、
org/postgresql/shaded/com/ongres/scram/配下のエントリとパッケージを列挙して比較したもの。 POM の依存宣言も同じ経路で確認している - 反例の実測:「外部の
com.ongres.scram:clientを足しても解決しない」は、同じサーバ・同じユーザーに対し、 42.2.0 の隣へclient/common/saslprep/stringprepを classpath に置いて接続して確かめている (同じNoClassDefFoundError・同じフレーム)。外部 artifact が公開するのはcom/ongres/scram/client/ScramClientで、org/postgresql/で始まるエントリを 1 つも含まないことも jar の中身で確認した
再現から修正までは errfix の検証ハーネスが機械的に確認しています。42.2.0 の同梱漏れと 42.2.1 での修正は、
pgjdbc の CHANGELOG(42.2.0 の Known issues と 42.2.1 の Fixed、および該当の Pull Request)で確認しています。