jdx/mise · error

failed to create database

Error message

failed to create database {database}

What it means

mise's postgres daemon preset initializes a fresh data directory by running initdb and then, when the preset names a database other than the default 'postgres', spawning `postgres --single` with a piped CREATE DATABASE statement. If that single-user postgres process exits nonzero, mise gives up creating the database and bails with this message so the uninitialized staging directory is never promoted into place. It means the SQL submitted to the single-user server failed, typically due to an invalid database name or a broken postgres install.

Solutions

  1. Check the database name in the daemon preset for invalid or problematic characters and use a simple ASCII identifier.
  2. Verify the postgres installation works by running `postgres --version` and a manual `initdb`/single-user start; reinstall postgres if it crashes.
  3. Remove any partially staged daemon data directory and re-run the mise command so initialization starts from a clean slate.
  4. Run with MISE_DEBUG=1 to capture the underlying postgres stderr for the exact SQL failure.

Example fix

// before
daemons.postgres.database = "my-db-prod!"

// after
daemons.postgres.database = "my_db_prod"
Defensive patterns

Strategy: validation

Validate before calling

// Validate the database name before configuring the daemon preset
const ok = /^[A-Za-z0-9_]+$/;
if (!ok.test(database) || database === "") throw new Error("invalid database name for postgres preset");

Type guard

fn is_valid_db_name(db: &str) -> bool {
    !db.is_empty() && db.chars().all(|c| c.is_ascii_alphanumeric() || c == '_')
}

Try / catch

try {
  mise daemons start
} catch (e) {
  if (String(e).includes("failed to create database")) {
    console.error("Check the preset's database name and your postgres install; inspect staged data dir.");
  }
}

Prevention

When it happens

Trigger: Running daemon preset initialization for a postgres preset whose database is not "postgres": `postgres --single -D <staged_data> postgres` is spawned, the SQL `CREATE DATABASE "{database}";` is piped to stdin, and child.wait() returns a non-success exit status.

Common situations: A daemon preset declares a database name that trips single-user-mode quirks (reserved names, quoting issues from odd characters that slipped past validation), or the postgres install is partially broken so the single-user backend crashes on startup.

Understand the failure class

Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/cc54c28a58799f15. Report an issue: GitHub.

Appendix: source

Thrown at src/daemons/presets.rs:248

                || !database
                    .chars()
                    .all(|c| c.is_ascii_alphanumeric() || c == '_')
            {
                bail!("invalid database name");
            }
            let mut child = Command::new("postgres")
                .arg("--single")
                .arg("-D")
                .arg(&staged_data)
                .arg("postgres")
                .stdin(Stdio::piped())
                .spawn()?;
            writeln!(
                child.stdin.take().unwrap(),
                "CREATE DATABASE \"{database}\";"
            )?;
            if !child.wait()?.success() {
                bail!("failed to create database {database}");
            }
        }
        if std::fs::read_to_string(staged_data.join("PG_VERSION"))?.trim() != major {
            bail!("initdb and postgres have incompatible versions");
        }
    } else {
        std::fs::create_dir(&staged_data)?;
    }
    std::fs::write(staged_data.join(".mise-daemon-version"), marker)?;
    std::fs::rename(staged_data, data)?;
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn presets_render_local_persistent_daemons() {

View on GitHub (pinned to 533346cc37)