transact-rs/sqlx · error

failed to parse DATABASE_URL

Error message

failed to parse DATABASE_URL

What it means

This panic comes from `PgConnectOptions::from_str(&url).expect(...)` inside sqlx's internal test harness (`test_context`). It fires when the DATABASE_URL environment variable is set but is not a valid PostgreSQL connection URL that can be parsed into PgConnectOptions. Since sqlx uses `.expect`, it is a hard panic, not a recoverable error.

Source

Thrown at sqlx-postgres/src/testing/mod.rs:95

            .bind(&deleted_db_names)
            .execute(&mut conn)
            .await?;

        let _ = conn.close().await;
        Ok(Some(delete_db_names.len()))
    }

    async fn snapshot(_conn: &mut Self::Connection) -> Result<FixtureSnapshot<Self>, Error> {
        // TODO: I want to get the testing feature out the door so this will have to wait,
        // but I'm keeping the code around for now because I plan to come back to it.
        todo!()
    }
}

async fn test_context(args: &TestArgs) -> Result<TestContext<Postgres>, Error> {
    let url = dotenvy::var("DATABASE_URL").expect("DATABASE_URL must be set");

    let master_opts = PgConnectOptions::from_str(&url).expect("failed to parse DATABASE_URL");

    let pool = PoolOptions::new()
        // Postgres' normal connection limit is 100 plus 3 superuser connections
        // We don't want to use the whole cap and there may be fuzziness here due to
        // concurrently running tests anyway.
        .max_connections(20)
        // Immediately close master connections. Tokio's I/O streams don't like hopping runtimes.
        .after_release(|_conn, _| Box::pin(async move { Ok(false) }))
        .connect_lazy_with(master_opts);

    let master_pool = match once_lock_try_insert_polyfill(&MASTER_POOL, pool) {
        Ok(inserted) => inserted,
        Err((existing, pool)) => {
            // Sanity checks.
            assert_eq!(
                existing.connect_options().host,
                pool.connect_options().host,
                "DATABASE_URL changed at runtime, host differs"

View on GitHub (pinned to 03af8bcc57)

Solutions

  1. Fix DATABASE_URL so it is a valid Postgres URL, e.g. `postgres://user:password@host:5432/db`
  2. Percent-encode special characters in the username/password (e.g. `@` -> `%40`, `#` -> `%23`)
  3. Verify the variable is actually set and non-empty: `echo $DATABASE_URL` (shell quoting may have mangled it)
  4. Ensure the scheme is postgres:// or postgresql://, not another database's scheme
  5. If you are a sqlx user (not contributor), note this is the internal test harness — write your own pool setup instead of relying on sqlx's test module

Example fix

// before
DATABASE_URL=postgres@localhost/mydb   // malformed, missing ://
// after
DATABASE_URL=postgres://postgres:password@localhost:5432/mydb
Defensive patterns

Strategy: validation

Validate before calling

fn validate_database_url() -> Result<String, String> {
    match std::env::var("DATABASE_URL") {
        Ok(url) if !url.trim().is_empty() => {
            if url.starts_with("postgres://") || url.starts_with("postgresql://") {
                Ok(url)
            } else {
                Err(format!("DATABASE_URL has unsupported/missing scheme: {url}"))
            }
        }
        Ok(_) => Err("DATABASE_URL is empty".into()),
        Err(_) => Err("DATABASE_URL is not set".into()),
    }
}

Try / catch

let url = validate_database_url().unwrap_or_else(|e| panic!("{e}: set a valid postgres:// URL in .env"));

Prevention

When it happens

Trigger: Calling `test_context(args)` (sqlx's internal test helper) while DATABASE_URL is set to a malformed string — missing scheme (not postgres:// or postgresql://), bad characters, invalid percent-encoding, or garbage text.

Common situations: CI or local test environments where DATABASE_URL is set to an empty string, contains typos (e.g. missing `://`), has unescaped special characters in the password, or points to a non-Postgres scheme like `mysql://`. Also common when .env files are stale or overwritten by CI variables.

Understand the failure class

Related errors


AI-assisted analysis of transact-rs/sqlx@03af8bcc57 (2026-09-03). Data as JSON: /api/errors/30375e07a28179b0. Report an issue: GitHub.