PostgreSQL Undefined File (SQLSTATE 58P01)

PostgreSQL raises ERROR: could not open file "<path>": No such file or directory with SQLSTATE 58P01 and condition name undefined_file when the server attempts to open a file that does not exist at the expected location. This is a system-level I/O error, not a SQL-logic error, meaning it originates from the operating system rather than from the query itself.

What This Error Means

SQLSTATE 58P01 belongs to PostgreSQL error class 58 — "System Error (errors external to PostgreSQL itself)." Class 58 errors indicate that something went wrong at the OS or filesystem level, outside of PostgreSQL's own SQL processing. The P in 58P01 marks it as a PostgreSQL-specific extension to the SQL standard class 58.

When PostgreSQL raises undefined_file, it has attempted a low-level open() or equivalent system call on a file path and received ENOENT (no such file or directory) back from the OS. This can happen during server startup, when loading a shared library extension, when executing a LOAD command, or when certain built-in functions try to read files from the data directory.

Unlike errors in class 22 (data exceptions) or 23 (integrity constraint violations), a class 58 error does not leave the current transaction in an aborted state by itself — but it will typically abort the current statement. The session remains usable unless the error occurs during a critical phase of server startup, in which case PostgreSQL will refuse to start or will shut down.

Common Causes

  1. Missing or uninstalled shared library for an extension. Running CREATE EXTENSION or LOAD for an extension (e.g., pg_stat_statements, postgis, pgvector) when the corresponding .so file is not present in $libdir (usually /usr/lib/postgresql/<version>/lib/). This is the most common cause.

  2. Extension installed for a different PostgreSQL major version. The .so file exists but was compiled for a different major version. PostgreSQL looks for version-specific paths and will fail to find the correct file.

  3. Manual LOAD of a nonexistent library path. Executing LOAD 'some_library' with a path that resolves to a missing file, either because the library was never installed or was removed.

  4. shared_preload_libraries references a missing library. A library name listed in postgresql.conf under shared_preload_libraries is not present on the filesystem. This causes PostgreSQL to fail at startup with this error.

  5. Incorrect $libdir or dynamic_library_path configuration. The library exists but is installed in a non-standard path not covered by dynamic_library_path, so PostgreSQL cannot locate it.

  6. File permissions or SELinux/AppArmor denial logged as a missing file. On some OS configurations, a permission denial on the .so file may surface as "No such file or directory" at the PostgreSQL level.

How to Fix undefined_file

  1. Install the missing extension package. For system-packaged PostgreSQL, the extension's .so file is usually in a separate OS package:

    # Debian/Ubuntu
    sudo apt-get install postgresql-<version>-<extension-name>
    
    # RHEL/Rocky/Alma
    sudo dnf install postgresql<version>-<extension-name>
    

    After installing, retry CREATE EXTENSION or LOAD without restarting PostgreSQL (for most extensions).

  2. Verify the library is in the right location. PostgreSQL's pg_config --pkglibdir tells you where it expects .so files:

    pg_config --pkglibdir
    # e.g. /usr/lib/postgresql/16/lib
    
    ls /usr/lib/postgresql/16/lib/pg_stat_statements.so
    

    If the file is present but in a different directory, either move it or add that directory to dynamic_library_path in postgresql.conf.

  3. Fix shared_preload_libraries before restarting. If the error occurs at startup, edit postgresql.conf and remove or correct the offending library name, then start PostgreSQL:

    -- Check what is currently configured (from a running instance)
    SHOW shared_preload_libraries;
    
    # Edit postgresql.conf and comment out or correct the bad entry
    sudo nano /etc/postgresql/16/main/postgresql.conf
    # shared_preload_libraries = 'pg_stat_statements'  -- remove the missing one
    
    sudo systemctl start postgresql
    
  4. Extend dynamic_library_path to cover a non-standard install location. In postgresql.conf:

    dynamic_library_path = '$libdir:/opt/custom_extensions'
    

    Reload the configuration with SELECT pg_reload_conf(); or pg_ctl reload.

  5. Check file permissions. Ensure the PostgreSQL process user (typically postgres) has read and execute permission on the .so file:

    ls -la /path/to/library.so
    sudo chmod 755 /path/to/library.so
    sudo chown root:root /path/to/library.so
    

Additional Information

  • SQLSTATE class 58 contains only a handful of conditions. The sibling codes most commonly encountered are 58000 (system_error, a generic I/O failure) and 58030 (io_error, raised for read/write failures on existing files). 58P01 is specifically for missing files.
  • This error is distinct from 42883 (undefined_function) or 42704 (undefined_object) — those are SQL-catalog lookup failures, not filesystem errors.
  • Client drivers (libpq, psycopg, JDBC, node-postgres) surface this as a server-side error with sqlstate = "58P01". Because it is a server error, it is raised before any query results are returned, and the driver's normal error-handling path applies.
  • On Docker or Kubernetes deployments, this error frequently appears when an extension is installed in a custom image layer but the production image was not rebuilt, or when a volume mount shadows the directory containing extension libraries.
  • PostgreSQL versions 14 and later produce more detailed error messages for some 58P01 cases, including the full resolved path that was attempted.

Frequently Asked Questions

Why does PostgreSQL say the file is missing when I can see it on disk? The most common reasons are: the file is owned or permissioned such that the postgres OS user cannot read it; SELinux or AppArmor is denying access and the kernel reports it as ENOENT; or the file exists in a path not searched by dynamic_library_path. Run ls -la on the file and check dynamic_library_path with SHOW dynamic_library_path;.

Can I get 58P01 from a regular SQL query, not just extension loading? Rarely, but yes. A few built-in functions read files directly — for example, pg_read_file() will raise 58P01 if the requested file does not exist. Custom functions written in PL/Python, PL/Perl, or C that perform file I/O can also trigger it.

Does 58P01 abort my transaction? The statement that caused the error is aborted. If you were inside a transaction block, the transaction enters the aborted state and you must issue ROLLBACK before issuing new commands. The session itself remains open unless the error occurred during server startup.

How do I find which library is causing a startup failure? Check the PostgreSQL server log — the 58P01 message includes the filename that could not be opened. On Linux, the default log location is /var/log/postgresql/ or accessible via journalctl -u postgresql. The message will look like: FATAL: could not load library "/usr/lib/postgresql/16/lib/missing_ext.so": No such file or directory.

Subscribe to the Pulse Newsletter

Get early access to new Pulse features, insightful blogs & exclusive events , webinars, and workshops.

We use cookies to provide an optimized user experience and understand our traffic. To learn more, read our use of cookies; otherwise, please choose 'Accept Cookies' to continue using our website.