PostgreSQL『ERROR: could not access file … No such file or directory』の原因と対処

  • 作成日 2025.09.28
  • 更新日 2025.10.06
  • その他
PostgreSQL『ERROR: could not access file … No such file or directory』の原因と対処

拡張(CREATE EXTENSION / LOAD / PL言語 / C関数)で参照する共有ライブラリや制御ファイルが見つからないときに出る。典型は「could not access file “$libdir/xxx”: No such file or directory」や「could not open extension control file … .control: No such file or directory」。原因の切り分け、最短復旧、OS別の導入手順、コンテナやバージョン不一致の罠、自作C関数のパス解決、再発防止チェックリストまで。

エラーの意味と代表メッセージ

ERROR:  could not access file "$libdir/pg_stat_statements": No such file or directory
ERROR:  could not access file "pgvector": No such file or directory
ERROR:  could not open extension control file "/usr/share/postgresql/16/extension/hoge.control": No such file or directory
ERROR:  could not load library "$libdir/my_udf": No such file or directory

・「.so/.dll(共有ライブラリ)」または「.control(拡張制御ファイル)」が物理的に存在しない/参照パス外/名前違い

発生条件の早見表

□ 拡張パッケージ未導入(OSにモジュールがインストールされていない)
□ PostgreSQLのメジャーバージョンが違う(/lib/pgsql/…/ 直下のABI不一致)
□ 画像(Docker)を変えた/OSを変えた(musl vs glibc 等)→バイナリ不適合
□ CREATE FUNCTION ... LANGUAGE C/LOAD で $libdir/名前 がファイルと不一致
□ 拡張の .control ファイルが share/extension に無い
□ dynamic_library_path の設定ミスで探索パスから外れている
□ WindowsでDLLの依存が解決できない(PATH/依存DLL不足)

まず現状確認:何を探していて、どこを見に行くか

-- 1) 失敗した拡張/ライブラリ名を把握(エラーメッセージに出る)

-- 2) その拡張が「DBから見える」か(.control があるか)
SELECT name, default_version, installed_version
FROM pg_available_extensions
WHERE name IN ('pg_stat_statements','pgvector','postgis','plpython3u');

-- 3) 参照パスの確認
SHOW dynamic_library_path;        -- 共有ライブラリ探索パス($libdir を含むのが通常)
SHOW shared_preload_libraries;    -- 事前ロード対象(参考)
SHOW config_file; SHOW data_directory;

-- 4) サーバ側ファイルシステムの確認(OS側)
$ pg_config --pkglibdir   # = $libdir の実パス(.so/.dll が置かれる)
$ pg_config --sharedir    # sharedir/extension に .control/.sql が置かれる
$ ls $(pg_config --sharedir)/extension | grep <名前>
$ ls $(pg_config --pkglibdir) | grep <名前>

・pg_available_extensions に出ない場合は「.control がない」=拡張パッケージ未導入と判断できる

最短復旧:拡張パッケージを導入 → CREATE EXTENSION

-- Debian/Ubuntu 系(例:pg_stat_statements は本体同梱、多くは postgresql-XX-<拡張>)
$ sudo apt-get update
$ sudo apt-get install postgresql-16-pgvector   # 例:pgvector
$ sudo apt-get install postgresql-16-postgis    # 例:PostGIS

-- RHEL/CentOS/Rocky 等
$ sudo dnf install postgresql16-pgvector
$ sudo dnf install postgis36_16

-- Alpine(musl)などは対応パッケージ/イメージを選択(後述)

-- 導入後にDBで
CREATE EXTENSION pgvector;      -- または CREATE EXTENSION postgis;

・パッケージ名はディストリ/バージョンで変わる(pg_config でバージョン確認→適合のものを選ぶ)

Docker/コンテナの罠(イメージ乗り換え時の「無い」)

# 例:公式 postgres:16 には PostGIS/pgvector は含まれない
# 必要な拡張入りのベースイメージに切り替える or 拡張をビルド/追加
FROM postgres:16
RUN apt-get update && apt-get install -y postgresql-16-pgvector && rm -rf /var/lib/apt/lists/*

# PostGISが必要なら postgis/postgis:16-* 系イメージを使うのが簡単

・イメージを変えると「.so/.control が消える」→そのままCREATE EXTENSIONで失敗
・Compose/Helmで複数サービスが別イメージを参照していないかを確認

pg_stat_statements など「事前ロードが必要」系

-- ライブラリ自体が無ければ「could not access file」、あれば事前ロードが必要なことも
ALTER SYSTEM SET shared_preload_libraries = 'pg_stat_statements';
SELECT pg_reload_conf();  -- ※要再起動のケースが多い
CREATE EXTENSION pg_stat_statements;

・「ファイルが無い」エラーを解消しても、preload必須の拡張は設定→再起動→CREATEの順序

CREATE FUNCTION/LOAD(C言語UDF)のパスと名前解決

-- サンプル:C関数をロード
LOAD 'my_udf';        -- 実際には $libdir/my_udf.so を探す
-- → 無ければ "could not access file "$libdir/my_udf": No such file or directory"

-- 置き場所の原則
$libdir = $(pg_config --pkglibdir) 直下に my_udf.so を配置
-- あるいは dynamic_library_path に含まれるディレクトリへ配置

-- CREATE FUNCTION も同様に $libdir/名前 を探す
CREATE FUNCTION f(...) RETURNS ...
AS 'my_udf', 'symbol_name' LANGUAGE C;

・拡張経由(CREATE EXTENSION)ではなく自前UDFなら「ビルド→$libdirに配置→権限」を確認

Windows特有の注意(DLL依存/パス)

-- DLL本体(my_udf.dll)と依存DLLが PATH で解決可能か
-- x64/x86 の混在に注意(サーバのbit数と一致させる)
-- PostgreSQLメジャーとビルド環境の一致(VC++ランタイム)も要確認

・DLLがあっても依存が解決できなければ読み込み失敗(まれに別メッセージだが原因は同系統)

名前不一致・拡張名の見間違いを疑う

-- 利用可能な拡張名の正確なスペルを確認
SELECT name, comment FROM pg_available_extensions ORDER BY name;

-- 例:plpython は plpython3u(手元のビルドにより異なる)
CREATE EXTENSION plpython3u;  -- 無ければ "could not access file 'plpython3' ..." に近いエラー

・README/記事のコピペで名称だけ古いケースが頻出

ABI/バージョン不一致(メジャー上げ後の“前の.so”)

-- パスに古いバージョンの .so を残していないか
$ ls /usr/lib/postgresql/15/lib/ | grep pgvector
$ ls /usr/lib/postgresql/16/lib/ | grep pgvector

-- メジャーアップグレード時は、拡張も「新バージョンのパッケージ」を再導入
$ sudo apt-get install postgresql-16-pgvector

・PostgreSQLはメジャーでABIが変わる。古い .so は16の$libdirでは使えない

dynamic_library_path をカスタムしている場合

SHOW dynamic_library_path;
-- 既定は "$libdir"(または $libdir:$libdir/plugins 等)
-- もし $libdir を消している/相対パスにしているなら元に戻す
ALTER SYSTEM SET dynamic_library_path = '$libdir';
SELECT pg_reload_conf();

・意図せず探索パスから外していると「存在しても見つからない」

再現→解消の通し例(NG→OK)

-- 1) 未導入拡張を作ろうとして失敗
CREATE EXTENSION pgvector;
-- ERROR: could not access file "pgvector": No such file or directory
-- もしくは
-- ERROR: could not open extension control file ".../extension/pgvector.control": No such file or directory

-- 2) OS側に拡張を導入
$ sudo apt-get update
$ sudo apt-get install postgresql-16-pgvector

-- 3) DBで作成
CREATE EXTENSION pgvector;        -- OK
SELECT * FROM pg_extension WHERE extname='pgvector';

-- 4) C UDF の例
CREATE FUNCTION hello() RETURNS text
AS 'my_udf', 'hello' LANGUAGE C;  -- ERROR: could not access file "$libdir/my_udf": No such file or directory

-- 5) $libdir に my_udf.so を配置(ビルド→インストール)
$ make && sudo make install    # 拡張/モジュールのMakefileに依存
-- 再試行
CREATE FUNCTION hello() RETURNS text
AS 'my_udf', 'hello' LANGUAGE C;  -- OK

OS別/代表拡張の導入ヒント集

-- Debian/Ubuntu(バージョンは環境に合わせて)
sudo apt-get install postgresql-16-contrib      # 多くの標準拡張
sudo apt-get install postgresql-16-pgvector
sudo apt-get install postgresql-16-plpython3
sudo apt-get install postgresql-16-postgis

-- RHEL系
sudo dnf install postgresql16-contrib
sudo dnf install postgresql16-pgvector
sudo dnf install postgis36_16

-- Docker(公式)
FROM postgres:16
RUN apt-get update && apt-get install -y postgresql-16-contrib postgresql-16-pgvector

・パッケージ名はディストリ毎に異なるため、リポジトリ検索で正確な名前を確認

自作/配布物のビルド(.control/.sql/.so の3点)

# 典型的な拡張構成
myext.control        -> $(pg_config --sharedir)/extension/
myext--1.0.sql       -> $(pg_config --sharedir)/extension/
myext.so             -> $(pg_config --pkglibdir)/

# ビルド・インストール
make
sudo make install

# その後 DBで
CREATE EXTENSION myext;

・.control と .sql が share/extension、.so が $libdir に入っているかがポイント

チェックリスト(上から順に)

□ pg_available_extensions に目的の拡張が見えるか(= .control があるか)
□ $(pg_config --pkglibdir) に .so(または .dll)が存在するか
□ dynamic_library_path に $libdir が含まれているか
□ OS/コンテナに適合する拡張パッケージを入れたか(メジャー/ABI一致)
□ 名称間違いをしていないか(plpython3u 等)
□ 事前ロードが必要な拡張は shared_preload_libraries → 再起動 → CREATE の順序で
□ 自作C UDFは $libdir 配置&依存解決(WindowsはPATH/DLL)を確認

まとめ:ファイルの“場所”と“適合”を揃えれば解消する

・エラーは「探しに行ったパスに対象が無い」が本質
・OS/コンテナに拡張パッケージを入れる → パス($libdir/sharedir)を確認
・メジャー/ABIと名称の一致、preload要否を満たしてから CREATE EXTENSION/LOAD を実行