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
- Build the postgres distributions (e.g. make postgres in the neon repo) so pg_install/v{14..17}/{bin,lib} exist
- Set pg_distrib_dir in the env config to the directory that actually contains v<major>/bin
- 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
- Run make postgres before any storcon start
- Pin pg_distrib_dir to an absolute path in CI
- Smoke-test that <pg_distrib_dir>/v16/bin/initdb exists
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
- id mismatch: identity.toml:id={identity_toml_id} pageserver_
- createdb failed with status {}: {stderr}
- initdb failed with status {status}
- Failed to start postgres {}
- Timed out waiting for postgres to start
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/85d818afeeae74d0.
Report an issue: GitHub.