SQL Lab Error Handling#
SQL Lab's error handling is a multi-layered pipeline that converts raw database driver exceptions into typed, user-facing SupersetError objects. Each layer is responsible for a distinct concern: query execution, error extraction, error categorization, and surfacing to the client.
Core Data Types#
All errors are represented as SupersetError dataclasses with four fields:
message– human-readable stringerror_type– aSupersetErrorTypeenum value (e.g.,SYNTAX_ERROR,COLUMN_DOES_NOT_EXIST_ERROR,GENERIC_DB_ENGINE_ERROR)level– anErrorLevel(info,warning, orerror)extra– optional dict; automatically populated withissue_codesbased onERROR_TYPES_TO_ISSUE_CODES_MAPPING
SQL Lab-specific error types include SQLLAB_TIMEOUT_ERROR, DML_NOT_ALLOWED_ERROR, RESULTS_BACKEND_ERROR, ASYNC_WORKERS_ERROR, and others.
Error Extraction: db_engine_spec#
Each database engine spec (subclass of BaseEngineSpec) defines a custom_errors dict mapping compiled regex patterns to (message_template, SupersetErrorType, extra_dict) tuples.
extract_errors() on BaseEngineSpec:
- Calls
_extract_error_message(ex)to get the raw error string from the exception - Iterates
custom_errorsregexes; on a match, fillsmessage_templatewith named capture groups and anycontextdict (e.g.,hostname,username,portfrom the connection URL) - If no regex matches, falls back to
GENERIC_DB_ENGINE_ERROR
Engine-specific overrides:
- MySQL – maps access denied, unknown hostname, host down, unknown database, and syntax errors
- PostgreSQL – maps invalid username/password, hostname resolution failure, port closed, column does not exist, and syntax errors
extract_error_message() is a simpler string-only variant used when structured error context isn't needed (e.g., inside execute_query).
Execution Pipeline#
Synchronous path#
ExecuteSqlCommand.run()
└─ _run_sql_json_exec_from_scratch()
└─ SqlJsonExecutor.execute()
└─ get_sql_results() [Celery task or direct call]
└─ execute_sql_statements()
└─ execute_query() [per-statement]
-
execute_query()— callsdb_engine_spec.execute_with_cursor()andfetch_data(). OnSoftTimeLimitExceeded, raisesSupersetErrorException(SQLLAB_TIMEOUT_ERROR). On generic exceptions, callsdb_engine_spec.extract_error_message(ex)and raisesSqlLabException. -
execute_sql_statements()— loops over SQL blocks; on any exception fromexecute_query(), callshandle_query_error()which:- Sets
query.status = FAILEDand recordsquery.error_message - If the exception is
SupersetErrorExceptionorSupersetErrorsException, uses the pre-built errors directly - Otherwise calls
db_engine_spec.extract_errors(str(ex))to produce structured errors - Stores errors in
query.extra_json["errors"]and returns them in the payload
- Sets
-
SynchronousSqlJsonExecutor.execute()— on FAILED status with a richerrorslist, raisesSupersetErrorsException; with an old-style string error, raisesSupersetGenericDBErrorException. -
ExecuteSqlCommand.run()— passesSupersetErrorException/SupersetErrorsExceptionthrough unchanged; wraps any other unexpected exception inSqlLabException.
Asynchronous path#
ASynchronousSqlJsonExecutor.execute() submits get_sql_results as a Celery task. If the task dispatch fails, it creates a SupersetError(ASYNC_WORKERS_ERROR), stores it in query.extra_json, and raises SupersetErrorException. The Celery task itself uses the same handle_query_error() path.
Connection Test Errors#
TestConnectionDatabaseCommand.run() surfaces connection errors distinctly from query execution errors:
DBAPIError→ callsdb_engine_spec.extract_errors(ex, context)(with connection context including hostname/port/username) → raisesSupersetErrorsExceptionNoSuchModuleError→ raisesDatabaseTestConnectionDriverError(missing driver)- Timeout → raises
SupersetTimeoutException(CONNECTION_DATABASE_TIMEOUT) - Other exceptions → also calls
extract_errorsand raisesDatabaseTestConnectionUnexpectedError
Metadata DB vs. Target DB#
A common confusion point: SQL Lab errors can originate from two different databases:
- Target database – the user's data source; errors from query execution are extracted via
extract_errors()on the engine spec - Superset metadata database – stores query records;
SQLAlchemyErroronquery_dao.create()raisesSqlLabException(GENERIC_DB_ENGINE_ERROR). In Celery deployments, authentication failures against the metadata DB (e.g., mismatchedSECRET_KEYorSQLALCHEMY_DATABASE_URIbetween web and worker pods) can surface as misleading "Invalid login" errors rather than clear DB engine errors.
Key Files#
| File | Role |
|---|---|
superset/errors.py | SupersetError, SupersetErrorType, ErrorLevel, issue code mappings |
superset/db_engine_specs/base.py | extract_errors(), extract_error_message(), custom_errors base class |
superset/db_engine_specs/mysql.py | MySQL custom_errors overrides |
superset/db_engine_specs/postgres.py | PostgreSQL custom_errors overrides |
superset/sql_lab.py | handle_query_error(), execute_query(), execute_sql_statements() |
superset/sqllab/sql_json_executer.py | Sync/async executors, error re-raising |
superset/commands/sql_lab/execute.py | ExecuteSqlCommand, query lifecycle, metadata DB errors |
superset/commands/database/test_connection.py | Connection test error handling |