neondatabase/neon · error · anyhow::Error

Postgres directory '{}' not found in {}

Error message

Postgres directory '{}' not found in {}

What it means

The storage controller's local runner needs a postgres distribution for its own database and for computes. It probes pg_distrib_dir/v<major>/<dir> for a preferred list of majors (PG14 through PG17), looking for the requested subdir ('bin' or 'lib'); if none exists it falls through to this error, naming the wanted dir and the configured pg_distrib_dir.

Source

Thrown at control_plane/src/storage_controller.rs:205

    /// where only one version is available in pg_distrib_dir, such as `test_remote_extensions`.
    async fn get_pg_dir(&self, dir_name: &str) -> anyhow::Result<Utf8PathBuf> {
        const PREFER_VERSIONS: [PgMajorVersion; 5] = [
            STORAGE_CONTROLLER_POSTGRES_VERSION,
            PgMajorVersion::PG16,
            PgMajorVersion::PG15,
            PgMajorVersion::PG14,
            PgMajorVersion::PG17,
        ];

        for v in PREFER_VERSIONS {
            let path = Utf8PathBuf::from_path_buf(self.env.pg_dir(v, dir_name)?).unwrap();
            if tokio::fs::try_exists(&path).await? {
                return Ok(path);
            }
        }

        // Fall through
        anyhow::bail!(
            "Postgres directory '{}' not found in {}",
            dir_name,
            self.env.pg_distrib_dir.display(),
        );
    }

    pub async fn get_pg_bin_dir(&self) -> anyhow::Result<Utf8PathBuf> {
        self.get_pg_dir("bin").await
    }

    pub async fn get_pg_lib_dir(&self) -> anyhow::Result<Utf8PathBuf> {
        self.get_pg_dir("lib").await
    }

    /// Readiness check for our postgres process
    async fn pg_isready(&self, pg_bin_dir: &Utf8Path, postgres_port: u16) -> anyhow::Result<bool> {
        let bin_path = pg_bin_dir.join("pg_isready");
        let args = [

View on GitHub (pinned to 8f60b04da4)

Solutions

  1. Build the postgres distributions (e.g. make postgres in the neon repo) so pg_install/v{14..17}/{bin,lib} exist
  2. Set pg_distrib_dir in the env config to the directory that actually contains v<major>/bin
  3. Smoke-test with ls: <pg_distrib_dir>/v16/bin/initdb should exist

Example fix

# before (env config)
pg_distrib_dir = "pg_install"
# after — absolute path to the real distribution root containing v14/…/v17
pg_distrib_dir = "/abs/path/to/neon/pg_install"
Defensive patterns

Strategy: validation

Validate before calling

let pg_root = env.pg_distrib_dir_raw();
let ok = ["v14", "v15", "v16", "v17"].iter().any(|v| {
    ["bin", "lib"].iter().all(|d| pg_root.join(v).join(d).is_dir())
});
anyhow::ensure!(ok, "no pg distribution found under {}", pg_root.display());

Prevention

When it happens

Trigger: pg_distrib_dir in the env config points at a path without built distributions, the repo's postgres distributions were never built, or the vXX directory layout differs (flat bin/ instead of v16/bin).

Common situations: Fresh clone where only cargo components were built but make postgres was skipped, a custom pg_distrib_dir in the env config, moving pg_install, or packaging that flattens version directories.

Related errors


AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16). Data as JSON: /api/errors/85d818afeeae74d0. Report an issue: GitHub.