neondatabase/neon · error
pg_ctl status returned no status code
Error message
pg_ctl status returned no status code
What it means
The status check asks for pg_ctl's exit code and gets none (ExitStatus::code() returns None), which happens only when the process was terminated by a signal rather than exiting normally.
Source
Thrown at control_plane/src/storage_controller.rs:774
let pg_data_path = self.env.base_data_dir.join("storage_controller_db");
let pg_status_args = ["-D", &pg_data_path.to_string_lossy(), "status"];
let status_exitcode = self.pg_ctl(pg_status_args).await;
// pg_ctl status returns this exit code if postgres is not running: in this case it is
// fine that stop failed. Otherwise it is an error that stop failed.
const PG_STATUS_NOT_RUNNING: i32 = 3;
const PG_NO_DATA_DIR: i32 = 4;
const PG_STATUS_RUNNING: i32 = 0;
match status_exitcode.code() {
Some(PG_STATUS_NOT_RUNNING) => Ok(false),
Some(PG_NO_DATA_DIR) => Ok(false),
Some(PG_STATUS_RUNNING) => Ok(true),
Some(code) => Err(anyhow::anyhow!(
"pg_ctl status returned unexpected status code: {:?}",
code
)),
None => Err(anyhow::anyhow!("pg_ctl status returned no status code")),
}
}
fn get_claims_for_path(path: &str) -> anyhow::Result<Option<Claims>> {
let category = match path.find('/') {
Some(idx) => &path[..idx],
None => path,
};
match category {
"status" | "ready" => Ok(None),
"control" | "debug" => Ok(Some(Claims::new(None, Scope::Admin))),
"v1" => Ok(Some(Claims::new(None, Scope::PageServerApi))),
_ => Err(anyhow::anyhow!("Failed to determine claims for {}", path)),
}
}
/// Simple HTTP request wrapper for calling into storage controllerView on GitHub (pinned to 8f60b04da4)
Solutions
- Check kernel logs (dmesg) for an OOM kill of pg_ctl and free memory
- Remove whatever sends the signal (kill scripts, reapers) and retry the stop/status operation
Defensive patterns
Strategy: fallback
Try / catch
match status.code() {
Some(code) => classify(code),
None => {
// pg_ctl was signalled; fall back to postmaster.pid liveness
check_postmaster_pid_alive(&pg_data_path)
}
} Prevention
- Watch memory usage on CI hosts to avoid OOM kills of pg_ctl
- Avoid kill -9 on process trees that include pg_ctl
- Fall back to postmaster.pid checks when exit codes are unavailable
When it happens
Trigger: pg_ctl is killed by a signal while running status — OOM killer, manual kill -9, or a test environment reaping process trees.
Common situations: Memory-pressured CI machines OOM-killing helper processes, parallel test teardown killing whole process groups.
Related errors
- Failed to start postgres {}
- Failed to stop storage controller database
- Failed to stop storage controller database: {err}
- pg_ctl status returned unexpected status code: {:?}
- pg_ctl failed, exit code: {}, stdout: {}, stderr: {}
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/9a32f0e2a41dadae.
Report an issue: GitHub.