neondatabase/neon · error · anyhow::Error
createdb failed with status {}: {stderr}
Error message
createdb failed with status {}: {stderr} What it means
The storage controller's control database is created by spawning the postgres createdb binary against the locally started postgres instance. If createdb exits non-zero and its stderr does not contain 'already exists', the raw exit status and stderr are surfaced with this error.
Source
Thrown at control_plane/src/storage_controller.rs:291
"-p",
&format!("{postgres_port}"),
"-U",
&username(),
"-O",
&username(),
DB_NAME,
])
.envs(envs)
.output()
.await
.expect("Failed to spawn createdb");
if !output.status.success() {
let stderr = String::from_utf8(output.stderr).expect("Non-UTF8 output from createdb");
if stderr.contains("already exists") {
tracing::info!("Database {DB_NAME} already exists");
} else {
anyhow::bail!("createdb failed with status {}: {stderr}", output.status);
}
}
Ok(database_url)
}
pub async fn connect_to_database(
&self,
postgres_port: u16,
) -> anyhow::Result<(
tokio_postgres::Client,
tokio_postgres::Connection<tokio_postgres::Socket, tokio_postgres::tls::NoTlsStream>,
)> {
tokio_postgres::Config::new()
.host("localhost")
.port(postgres_port)
// The user is the ambient operating system user name.
// That is an impurity which we want to fix in => TODO https://github.com/neondatabase/neon/issues/8400View on GitHub (pinned to 8f60b04da4)
Solutions
- Read the embedded stderr — createdb states the exact reason (connection refused, auth failed, invalid name)
- Confirm postgres is still up on the expected port (pg_isready) right before createdb runs
- Fix credentials/pg_hba so createdb can authenticate as the configured user
- Drop the inconsistent database and retry start
Defensive patterns
Strategy: validation
Validate before calling
// check the database is absent before running createdb
let exists: bool = client
.query_opt("SELECT 1 FROM pg_database WHERE datname = $1", &[&DB_NAME])
.await?
.is_some();
if exists { /* skip createdb entirely */ } Try / catch
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
if stderr.contains("already exists") { /* fine */ }
else if stderr.contains("connection refused") || stderr.contains("does not exist") { /* postgres gone: restart and retry */ }
else { anyhow::bail!("createdb failed: {stderr}"); }
} Prevention
- Verify pg_isready immediately before createdb
- Keep storcon's postgres auth in sync with the env config
- Skip creation idempotently when the database already exists
When it happens
Trigger: createdb cannot reach the server (postgres not accepting connections on postgres_port), authentication fails (pg_hba/missing password), the database name is invalid, or a locale/encoding option is unsupported.
Common situations: postgres exiting between pg_isready succeeding and createdb running, auth configuration drift between storcon and its local postgres, or half-created database state not covered by the 'already exists' string match.
Related errors
- initdb failed with status {status}
- postgres --sync-safekeepers exited with non-zero status: {}.
- pg_ctl failed, exit code: {}, stdout: {}, stderr: {}
- Postgres directory '{}' not found in {}
- Failed to start postgres {}
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/25667aa794862d28.
Report an issue: GitHub.