Documentssuperset
SQL Lab Error Handling
SQL Lab Error Handling
Type
Topic
Status
Published
Created
Jul 17, 2026
Updated
Jul 17, 2026

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 string
  • error_type – a SupersetErrorType enum value (e.g., SYNTAX_ERROR, COLUMN_DOES_NOT_EXIST_ERROR, GENERIC_DB_ENGINE_ERROR)
  • level – an ErrorLevel (info, warning, or error)
  • extra – optional dict; automatically populated with issue_codes based on ERROR_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:

  1. Calls _extract_error_message(ex) to get the raw error string from the exception
  2. Iterates custom_errors regexes; on a match, fills message_template with named capture groups and any context dict (e.g., hostname, username, port from the connection URL)
  3. 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]
  1. execute_query() — calls db_engine_spec.execute_with_cursor() and fetch_data(). On SoftTimeLimitExceeded, raises SupersetErrorException(SQLLAB_TIMEOUT_ERROR). On generic exceptions, calls db_engine_spec.extract_error_message(ex) and raises SqlLabException.

  2. execute_sql_statements() — loops over SQL blocks; on any exception from execute_query(), calls handle_query_error() which:

    • Sets query.status = FAILED and records query.error_message
    • If the exception is SupersetErrorException or SupersetErrorsException, 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
  3. SynchronousSqlJsonExecutor.execute() — on FAILED status with a rich errors list, raises SupersetErrorsException; with an old-style string error, raises SupersetGenericDBErrorException.

  4. ExecuteSqlCommand.run() — passes SupersetErrorException/SupersetErrorsException through unchanged; wraps any other unexpected exception in SqlLabException.

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 → calls db_engine_spec.extract_errors(ex, context) (with connection context including hostname/port/username) → raises SupersetErrorsException
  • NoSuchModuleError → raises DatabaseTestConnectionDriverError (missing driver)
  • Timeout → raises SupersetTimeoutException(CONNECTION_DATABASE_TIMEOUT)
  • Other exceptions → also calls extract_errors and raises DatabaseTestConnectionUnexpectedError

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; SQLAlchemyError on query_dao.create() raises SqlLabException(GENERIC_DB_ENGINE_ERROR) . In Celery deployments, authentication failures against the metadata DB (e.g., mismatched SECRET_KEY or SQLALCHEMY_DATABASE_URI between web and worker pods) can surface as misleading "Invalid login" errors rather than clear DB engine errors.

Key Files#

FileRole
superset/errors.pySupersetError, SupersetErrorType, ErrorLevel, issue code mappings
superset/db_engine_specs/base.pyextract_errors(), extract_error_message(), custom_errors base class
superset/db_engine_specs/mysql.pyMySQL custom_errors overrides
superset/db_engine_specs/postgres.pyPostgreSQL custom_errors overrides
superset/sql_lab.pyhandle_query_error(), execute_query(), execute_sql_statements()
superset/sqllab/sql_json_executer.pySync/async executors, error re-raising
superset/commands/sql_lab/execute.pyExecuteSqlCommand, query lifecycle, metadata DB errors
superset/commands/database/test_connection.pyConnection test error handling