apache/superset · error · ValidationError

Invalid connection string, a valid string usually follows: b

Error message

Invalid connection string, a valid string usually follows: backend+driver://user:password@database-host/database-name

What it means

Field validator for the SQLAlchemy URI on database create/update: make_url_safe (SQLAlchemy make_url) failed to parse the string as a URI, so the value cannot possibly be used as a connection string. The message shows the canonical backend+driver://user:password@host/db shape.

Source

Thrown at superset/databases/schemas.py:214

        "get": {
            "summary": "Get a list of databases",
            "description": "Gets a list of databases, use Rison or JSON query "
            "parameters for filtering, sorting, pagination and "
            " for selecting specific columns and metadata.",
        }
    },
    "info": {"get": {"summary": "Get metadata information about this API resource"}},
}


def sqlalchemy_uri_validator(value: str) -> str:
    """
    Validate if it's a valid SQLAlchemy URI and refuse SQLLite by default
    """
    try:
        uri = make_url_safe(value.strip())
    except DatabaseInvalidError as ex:
        raise ValidationError(
            [
                _(
                    "Invalid connection string, a valid string usually follows: "
                    "backend+driver://user:password@database-host/database-name"
                )
            ]
        ) from ex
    if current_app.config.get("PREVENT_UNSAFE_DB_CONNECTIONS", True):
        try:
            check_sqlalchemy_uri(uri)
        except SupersetSecurityException as ex:
            raise ValidationError([str(ex)]) from ex
    return value


def server_cert_validator(value: str) -> str:
    """
    Validate the server certificate

View on GitHub (pinned to f4587218dd)

Solutions

  1. Rewrite the URI in SQLAlchemy form: dialect+driver://user:password@host:port/database (e.g. postgresql+psycopg2://...).
  2. Strip whitespace, quotes, and newlines; ensure the password is URL-encoded if it contains special characters like @ or :.
  3. Test locally: from sqlalchemy.engine import make_url; make_url(uri).
  4. For ODBC/JDBC sources, use the corresponding SQLAlchemy dialect URI rather than the native DSN.

Example fix

# before
jdbc:postgresql://dbhost:5432/analytics

# after
postgresql+psycopg2://user:p%40ssw0rd@dbhost:5432/analytics
Defensive patterns

Strategy: validation

Validate before calling

from sqlalchemy.engine import make_url
try:
    make_url(uri.strip())
except Exception as e:
    raise ValueError(f"not a valid SQLAlchemy URI: {e}")

Type guard

def is_valid_sqlalchemy_uri(uri: str) -> bool:
    try:
        make_url(uri.strip())
        return True
    except Exception:
        return False

Prevention

When it happens

Trigger: POST/PUT /api/v1/database/ with sqlalchemy_uri that is empty-ish, lacks a scheme/delimiter, uses backslashes or spaces, or is a DSN in a dialect SQLAlchemy does not understand (e.g. an ODBC or JDBC string pasted verbatim).

Common situations: Pasting JDBC URLs (jdbc:postgresql://...) or pyodbc connection strings; missing '://'; typos like postgres://:host/db; copying URIs with quotes/newlines from password managers.

Related errors


AI-assisted analysis of apache/superset@f4587218dd (2026-08-14). Data as JSON: /api/errors/993ea84314db4597. Report an issue: GitHub.