{"record":{"id":"85d818afeeae74d0","repo":"neondatabase/neon","slug":"postgres-directory-not-found-in","errorCode":null,"errorMessage":"Postgres directory '{}' not found in {}","messagePattern":"Postgres directory '(.+?)' not found in (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"control_plane/src/storage_controller.rs","lineNumber":205,"sourceCode":"    /// where only one version is available in pg_distrib_dir, such as `test_remote_extensions`.\n    async fn get_pg_dir(&self, dir_name: &str) -> anyhow::Result<Utf8PathBuf> {\n        const PREFER_VERSIONS: [PgMajorVersion; 5] = [\n            STORAGE_CONTROLLER_POSTGRES_VERSION,\n            PgMajorVersion::PG16,\n            PgMajorVersion::PG15,\n            PgMajorVersion::PG14,\n            PgMajorVersion::PG17,\n        ];\n\n        for v in PREFER_VERSIONS {\n            let path = Utf8PathBuf::from_path_buf(self.env.pg_dir(v, dir_name)?).unwrap();\n            if tokio::fs::try_exists(&path).await? {\n                return Ok(path);\n            }\n        }\n\n        // Fall through\n        anyhow::bail!(\n            \"Postgres directory '{}' not found in {}\",\n            dir_name,\n            self.env.pg_distrib_dir.display(),\n        );\n    }\n\n    pub async fn get_pg_bin_dir(&self) -> anyhow::Result<Utf8PathBuf> {\n        self.get_pg_dir(\"bin\").await\n    }\n\n    pub async fn get_pg_lib_dir(&self) -> anyhow::Result<Utf8PathBuf> {\n        self.get_pg_dir(\"lib\").await\n    }\n\n    /// Readiness check for our postgres process\n    async fn pg_isready(&self, pg_bin_dir: &Utf8Path, postgres_port: u16) -> anyhow::Result<bool> {\n        let bin_path = pg_bin_dir.join(\"pg_isready\");\n        let args = [","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/control_plane/src/storage_controller.rs#L187-L223","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"# before (env config)\npg_distrib_dir = \"pg_install\"\n# after — absolute path to the real distribution root containing v14/…/v17\npg_distrib_dir = \"/abs/path/to/neon/pg_install\"","handlingStrategy":"validation","validationCode":"let pg_root = env.pg_distrib_dir_raw();\nlet ok = [\"v14\", \"v15\", \"v16\", \"v17\"].iter().any(|v| {\n    [\"bin\", \"lib\"].iter().all(|d| pg_root.join(v).join(d).is_dir())\n});\nanyhow::ensure!(ok, \"no pg distribution found under {}\", pg_root.display());","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["rust","neon-local","storage-controller","postgres","config","paths"],"backgroundTag":"missing-required-path","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}