{"record":{"id":"b56d41a130f4e4dc","repo":"neondatabase/neon","slug":"expected-a-directory-got","errorCode":null,"errorMessage":"expected a directory, got {:?}","messagePattern":"expected a directory, got (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"control_plane/src/local_env.rs","lineNumber":719,"sourceCode":"            \"we ensure this during deserialization\"\n        );\n        env.pageservers = {\n            let iter = std::fs::read_dir(repopath).context(\"open dir\")?;\n            let mut pageservers = Vec::new();\n            for res in iter {\n                let dentry = res?;\n                const PREFIX: &str = \"pageserver_\";\n                let dentry_name = dentry\n                    .file_name()\n                    .into_string()\n                    .ok()\n                    .with_context(|| format!(\"non-utf8 dentry: {:?}\", dentry.path()))\n                    .unwrap();\n                if !dentry_name.starts_with(PREFIX) {\n                    continue;\n                }\n                if !dentry.file_type().context(\"determine file type\")?.is_dir() {\n                    anyhow::bail!(\"expected a directory, got {:?}\", dentry.path());\n                }\n                let id = dentry_name[PREFIX.len()..]\n                    .parse::<NodeId>()\n                    .with_context(|| format!(\"parse id from {:?}\", dentry.path()))?;\n                // TODO(christian): use pageserver_api::config::ConfigToml (PR #7656)\n                #[derive(serde::Serialize, serde::Deserialize)]\n                // (allow unknown fields, unlike PageServerConf)\n                struct PageserverConfigTomlSubset {\n                    listen_pg_addr: String,\n                    listen_http_addr: String,\n                    listen_https_addr: Option<String>,\n                    listen_grpc_addr: Option<String>,\n                    pg_auth_type: AuthType,\n                    http_auth_type: AuthType,\n                    grpc_auth_type: AuthType,\n                    #[serde(default)]\n                    no_sync: bool,\n                }","sourceCodeStart":701,"sourceCodeEnd":737,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/control_plane/src/local_env.rs#L701-L737","documentation":"Thrown by neon_local's LocalEnv while discovering pageservers from the local environment's base data directory (default .neon). It scans every entry whose name starts with 'pageserver_' and expects each to be a directory holding that pageserver's datadir; an entry of any other file type aborts env setup before the node id is even parsed.","triggerScenarios":"A non-directory entry named pageserver_<anything> directly under the base data dir: a stray file (e.g. pageserver_1.bak or an editor backup), a symlink pointing to a file, or a marker file dropped by a script. read_dir yields it, file_type().is_dir() is false, and LocalEnv bails immediately.","commonSituations":"Manually copying or moving pageserver datadirs, partial cleanup after a crashed init/destroy, backup tools dropping files into .neon, or hand-editing the env directory instead of using the neon CLI.","solutions":["Inspect the path printed in the error and delete or rename the stray pageserver_* file so only real datadirs keep the prefix","Run the env destroy command and re-run init to rebuild a consistent directory layout","Ensure every pageserver datadir is a directory literally named pageserver_<NodeId> and keep notes/backups outside the base dir"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"fn validate_pageserver_entries(base: &std::path::Path) -> anyhow::Result<()> {\n    for entry in std::fs::read_dir(base)? {\n        let entry = entry?;\n        if entry.file_name().to_string_lossy().starts_with(\"pageserver_\") {\n            anyhow::ensure!(\n                entry.file_type()?.is_dir(),\n                \"stray non-dir entry: {}\",\n                entry.path().display()\n            );\n        }\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never create files directly under the env base dir; keep logs and notes elsewhere","After a failed init, run destroy before the next init","Treat any manual edit of .neon as requiring a full re-init"],"tags":["rust","neon-local","filesystem","pageserver","local-env"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}