Error [org/postgresql/shaded/com/ongres/scram/client/ScramClient$ChannelBinding]

NoClassDefFoundError: .../scram/client/ScramClient$ChannelBinding の直し方(pgjdbc 42.2.0 だけ SCRAM の実装が入っていない)

FIX SUMMARY verified
Applies when
postgres@sha256:33f923b05f64ca54ac4401c01126a6b92afe839a0aa0a52bc5aeb5cc958e5f20org.postgresql:postgresql 42.2.0 — the release that added SCRAM-SHA-256 support but shipped a jar without the shaded scram/client package (fixed in 42.2.1)following the common advice to upgrade pgjdbc to 42.2.0 or later after hitting 'The authentication type 10 is not supported', and landing exactly on 42.2.0 — the first error disappears and the SCRAM handshake stops on a missing class instead

Verified: reproduced in postgres@sha256:33f923b05f64ca54ac4401c01126a6b92afe839a0aa0a52bc5aeb5cc958e5f20, then the org/postgresql/shaded/com/ongres/scram/client/ScramClient$ChannelBinding signature was gone after the fix (exit 0).

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 / commonstringprep を 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.40無し(SCRAM 自体が未対応)
42.2.039無し
42.2.150あり
42.7.451あり

42.2.0 には scram/commonexception / 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:treeorg.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)で確認しています。

検証(machine-verified)

この修正は postgres@sha256:33f923b05f64ca54ac4401c01126a6b92afe839a0aa0a52bc5aeb5cc958e5f20 のバージョン固定コンテナ内で再現し、修正後に org/postgresql/shaded/com/ongres/scram/client/ScramClient$ChannelBinding のシグネチャが消えることを機械で確認しています。

verify — run-case.mjs
$ node run-case.mjs jvm/pgjdbc-scram-noclassdeffound
● reproduce org/postgresql/shaded/com/ongres/scram/client/ScramClient$ChannelBinding present ✓
● apply fix exit 0
● re-run org/postgresql/shaded/com/ongres/scram/client/ScramClient$ChannelBinding gone ✓
PASS verified · postgres@sha256:33f923b05f64ca54ac4401c01126a6b92afe839a0aa0a52bc5aeb5cc958e5f20 · signature gone

確認したのは上のイメージの中だけです。別の環境で直らなかった、記述が違う、という場合は 報告してください(対象と検証イメージは件名・本文に入ります)。