psycopg/psycopg2 · critical · Warning
pg_config --{attr_name} is empty
Error message
pg_config --{attr_name} is empty What it means
Raised in PostgresConfig.query() (setup.py:120) as a Warning when pg_config exited 0 but printed nothing for a required attribute (libdir, includedir, includedir-server). An empty result cannot drive the compiler/linker search paths, so the build aborts. Attributes queried with empty_ok=True (ldflags, cppflags) are exempt and will not trigger this; the required ones will.
Source
Thrown at setup.py:120
sys.exit(1)
def query(self, attr_name, *, empty_ok=False):
"""Spawn the pg_config executable, querying for the given config
name, and return the printed value, sanitized. """
try:
pg_config_process = subprocess.run(
[self.pg_config_exe, "--" + attr_name],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
except OSError:
raise Warning(
f"Unable to find 'pg_config' file in '{self.pg_config_exe}'")
if pg_config_process.returncode:
err = pg_config_process.stderr.decode(errors='backslashreplace')
raise Warning(f"pg_config --{attr_name} failed: {err}")
result = pg_config_process.stdout.decode().strip()
if not result and not empty_ok:
raise Warning(f"pg_config --{attr_name} is empty")
return result
def find_on_path(self, exename, path_directories=None):
if not path_directories:
path_directories = os.environ['PATH'].split(os.pathsep)
for dir_name in path_directories:
fullpath = os.path.join(dir_name, exename)
if os.path.isfile(fullpath):
return fullpath
return None
def autodetect_pg_config_path(self):
"""Find and return the path to the pg_config executable."""
if PLATFORM_IS_WINDOWS:
return self.autodetect_pg_config_path_windows()
else:
return self.find_on_path('pg_config')
View on GitHub (pinned to 3a6d9d6ddc)
Solutions
- Reinstall the proper PostgreSQL dev package so pg_config emits real paths.
- Verify manually: '/path/to/pg_config --includedir' and '--libdir' must each print a non-empty directory.
- Fall back to psycopg2-binary if the local pg_config cannot be repaired.
Defensive patterns
Strategy: validation
Validate before calling
import subprocess, shutil
def pg_config_attr_is_nonempty(attr: str, path: str | None = None) -> bool:
p = path or shutil.which('pg_config')
if not p:
return False
res = subprocess.run([p, '--' + attr], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return res.returncode == 0 and bool(res.stdout.decode().strip())
for attr in ('libdir', 'includedir', 'includedir-server'):
assert pg_config_attr_is_nonempty(attr), f'pg_config --{attr} returned empty' Try / catch
# Pre-build sanity check in CI:
# for a in libdir includedir includedir-server; do
# v="$(pg_config --$a)"; [ -n "$v" ] || { echo "empty $a"; exit 1; }
# done Prevention
- Use official PostgreSQL packages rather than stripped/custom pg_config shims.
- After installing the dev package, manually verify pg_config emits non-empty libdir/includedir.
- If a minimal image's pg_config is unreliable, switch to psycopg2-binary for the build.
When it happens
Trigger: During finalize_options(), pg_config_helper.query('libdir') / query('includedir') / query('includedir-server') returns an empty stdout despite exit code 0. Common with a stub or mispackaged pg_config that emits blank lines for some attributes.
Common situations: Custom/minimal container images shipping a stripped pg_config; very old or hand-built Postgres installs whose pg_config lacks certain keys; packaging bugs in third-party Postgres distributions.
Related errors
- Unable to find 'pg_config' file in '{self.pg_config_exe}'
- pg_config --{attr_name} failed: {err}
- no format specification supported by SQL
- no format conversion supported by SQL
- cannot switch from automatic field numbering to manual
AI-assisted analysis of psycopg/psycopg2@3a6d9d6ddc (2026-08-04).
Data as JSON: /data/errors/0e64f8387e9bf73a.json.
Report an issue: GitHub.