Skip to content

Show clear error for invalid sql_alchemy_conn at startup#68783

Open
GayathriSrividya wants to merge 1 commit into
apache:mainfrom
GayathriSrividya:fix/invalid-sqlalchemy-uri-help-cli-68707
Open

Show clear error for invalid sql_alchemy_conn at startup#68783
GayathriSrividya wants to merge 1 commit into
apache:mainfrom
GayathriSrividya:fix/invalid-sqlalchemy-uri-help-cli-68707

Conversation

@GayathriSrividya

@GayathriSrividya GayathriSrividya commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

This improves startup diagnostics when database connection configuration is malformed.

Context: this came from investigation in the discussion thread about slow CLI/help startup and the confusing unpacking traceback:
#68707

_get_async_conn_uri_from_sync now validates malformed/empty sync URIs and raises a clear, actionable error message that points users to AIRFLOW__DATABASE__SQL_ALCHEMY_CONN / sql_alchemy_conn in airflow.cfg, instead of failing with a cryptic unpacking error.

Changes in this PR:

  1. Add validation for malformed sync SQLAlchemy URI input in startup path.
  2. Raise a clearer ValueError with direct guidance to relevant config knobs.
  3. Add focused unit tests for:
  • valid URI conversions to async driver schemes
  • unsupported schemes passthrough
  • malformed/empty input behavior and error messaging

Discussion reference:

Users can hit a cryptic unpacking ValueError when sql_alchemy_conn is malformed, especially while diagnosing slow CLI startup in constrained environments. A clearer validation path makes misconfiguration immediately actionable and reduces support/debugging churn.
Comment on lines +508 to +526
def test_sqlite_uri_conversion(self):
"""Test conversion of SQLite sync URI to async with aiosqlite."""
result = settings._get_async_conn_uri_from_sync("sqlite:///path/to/db.sqlite")
assert result == "sqlite+aiosqlite:///path/to/db.sqlite"

def test_postgresql_uri_conversion(self):
"""Test conversion of PostgreSQL sync URI to async with asyncpg."""
result = settings._get_async_conn_uri_from_sync("postgresql://user:pass@localhost/dbname")
assert result == "postgresql+asyncpg://user:pass@localhost/dbname"

def test_mysql_uri_conversion(self):
"""Test conversion of MySQL sync URI to async with aiomysql."""
result = settings._get_async_conn_uri_from_sync("mysql://user:pass@localhost/dbname")
assert result == "mysql+aiomysql://user:pass@localhost/dbname"

def test_postgresql_psycopg2_uri_conversion(self):
"""Test conversion of PostgreSQL with psycopg2 driver to asyncpg."""
result = settings._get_async_conn_uri_from_sync("postgresql+psycopg2://user@localhost/db")
assert result == "postgresql+asyncpg://user@localhost/db"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it maybe make sense to parameterize these tests? It could be tightened up to something like:

@pytest.mark.parametrize(
    ("sync_uri", expected"),
    [
        ("sqlite:///path/to/db.sqlite", "sqlite+aiosqlite:///path/to/db.sqlite"),
        ("postgresql://user:pass@localhost/dbname", "postgresql+asyncpg://user:pass@localhost/dbname"),
        ("mysql://user:pass@localhost/dbname", "mysql+aiomysql://user:pass@localhost/dbname"),
        ("postgresql+psycopg2://user@localhost/db", "postgresql+asyncpg://user@localhost/db"),
    ],
)
    def test_supported_scheme_conversion(self, sync_uri, expected):
        assert settings._get_async_conn_uri_from_sync(sync_uri) == expected

Comment on lines +534 to +547
def test_empty_string_raises_value_error(self):
"""Test that empty string raises ValueError with helpful message."""
with pytest.raises(ValueError, match="Invalid SQLAlchemy connection URI"):
settings._get_async_conn_uri_from_sync("")

def test_none_raises_value_error(self):
"""Test that None raises ValueError with helpful message."""
with pytest.raises(ValueError, match="Invalid SQLAlchemy connection URI"):
settings._get_async_conn_uri_from_sync(None)

def test_malformed_uri_without_colon_raises_value_error(self):
"""Test that URI without ':' separator raises ValueError."""
with pytest.raises(ValueError, match="Invalid SQLAlchemy connection URI.*':' separator"):
settings._get_async_conn_uri_from_sync("notavaliduri")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can do the same with these tests as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants