{"record":{"id":"2d4c5e78cff45756","repo":"neondatabase/neon","slug":"failed-to-read-storcon-pid-file-at-pid-file","errorCode":null,"errorMessage":"Failed to read storcon pid file at {pid_file:?}: {err}","messagePattern":"Failed to read storcon pid file at (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"control_plane/src/storage_controller.rs","lineNumber":719,"sourceCode":"\n    pub async fn stop(&self, stop_args: NeonStorageControllerStopArgs) -> anyhow::Result<()> {\n        background_process::stop_process(\n            stop_args.immediate,\n            COMMAND,\n            &self.pid_file(stop_args.instance_id),\n        )?;\n\n        let storcon_instances = self.env.storage_controller_instances().await?;\n        for (instance_id, instanced_dir_path) in storcon_instances {\n            if instance_id == stop_args.instance_id {\n                continue;\n            }\n\n            let pid_file = instanced_dir_path.join(\"storage_controller.pid\");\n            let pid = tokio::fs::read_to_string(&pid_file)\n                .await\n                .map_err(|err| {\n                    anyhow::anyhow!(\"Failed to read storcon pid file at {pid_file:?}: {err}\")\n                })?\n                .parse::<i32>()\n                .expect(\"pid is valid i32\");\n\n            let other_proc_alive = !background_process::process_has_stopped(Pid::from_raw(pid))?;\n            if other_proc_alive {\n                // There is another storage controller instance running, so we return\n                // and leave the database running.\n                return Ok(());\n            }\n        }\n\n        let pg_data_path = self.env.base_data_dir.join(\"storage_controller_db\");\n\n        println!(\"Stopping storage controller database...\");\n        let pg_stop_args = [\"-D\", &pg_data_path.to_string_lossy(), \"stop\"];\n        let stop_status = self.pg_ctl(pg_stop_args).await;\n        if !stop_status.success() {","sourceCodeStart":701,"sourceCodeEnd":737,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/control_plane/src/storage_controller.rs#L701-L737","documentation":"When stopping one storage controller instance, storcon inspects every OTHER instance's storage_controller.pid file to decide whether the shared database must stay up. The read has no NotFound handling — any read error, including a missing pid file, is fatal to the stop command.","triggerScenarios":"Another storcon instance directory exists under the env but its storage_controller.pid is missing (deleted manually, instance never fully started) or unreadable (permissions), so stop cannot determine whether the database is still needed.","commonSituations":"Manually pruning instance dirs or pid files, mixed-version envs whose instances never wrote pid files, crashed instances that left a directory without a pid file.","solutions":["Restore or remove the stale instance directory so its pid file can be read or the instance is fully gone","Stop or clean up the other storcon instances (via the CLI) before stopping this one"],"exampleFix":"// before\nlet pid = tokio::fs::read_to_string(&pid_file).await\n    .map_err(|err| anyhow::anyhow!(\"Failed to read storcon pid file at {pid_file:?}: {err}\"))?;\n// after — treat a missing pid file as \"not running\"\nlet pid = match tokio::fs::read_to_string(&pid_file).await {\n    Ok(s) => s.parse::<i32>()?,\n    Err(e) if e.kind() == std::io::ErrorKind::NotFound => continue,\n    Err(e) => anyhow::bail!(\"Failed to read storcon pid file at {pid_file:?}: {e}\"),\n};","handlingStrategy":"validation","validationCode":"for (_, dir) in other_instances {\n    let pid_file = dir.join(\"storage_controller.pid\");\n    match tokio::fs::read_to_string(&pid_file).await {\n        Ok(s) => { let _pid: i32 = s.parse().context(\"malformed pid file\")?; }\n        Err(e) if e.kind() == std::io::ErrorKind::NotFound => continue, // no pid => not running\n        Err(e) => anyhow::bail!(\"unreadable pid file {pid_file:?}: {e}\"),\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never delete instance directories by hand; use the CLI","Stop instances in reverse order of creation","Treat a missing pid file as 'not running' rather than an error"],"tags":["rust","storage-controller","pid-file","filesystem","shutdown"],"backgroundTag":"pid-file-read-failed","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}