apache/superset · error · SupersetSecurityException

Only single queries supported

Error message

Only single queries supported

What it means

Raised by get_virtual_table_metadata() when the parsed SQLScript contains more than one statement. Virtual datasets support exactly one query; multiple statements are rejected with SupersetSecurityException (DATASOURCE_SECURITY_ACCESS_ERROR, 'Only single queries supported') even when each statement is a plain SELECT.

Source

Thrown at superset/connectors/sqla/utils.py:162

        # already persisted by ``UpdateDatasetCommand``. Genuinely
        # invalid static SQL must still hard-error. See #38012.
        if _has_jinja_markers(original_sql):
            raise SupersetVirtualTableParseException(
                message=_("Invalid SQL: %(error)s", error=ex.error.message),
            ) from ex
        raise SupersetGenericDBErrorException(
            message=_("Invalid SQL: %(error)s", error=ex.error.message),
        ) from ex
    if parsed_script.has_mutation():
        raise SupersetSecurityException(
            SupersetError(
                error_type=SupersetErrorType.DATASOURCE_SECURITY_ACCESS_ERROR,
                message=_("Only `SELECT` statements are allowed"),
                level=ErrorLevel.ERROR,
            )
        )
    if len(parsed_script.statements) > 1:
        raise SupersetSecurityException(
            SupersetError(
                error_type=SupersetErrorType.DATASOURCE_SECURITY_ACCESS_ERROR,
                message=_("Only single queries supported"),
                level=ErrorLevel.ERROR,
            )
        )
    return get_columns_description(
        dataset.database,
        dataset.catalog,
        dataset.schema,
        sql,
    )


def get_columns_description(
    database: Database,
    catalog: str | None,
    schema: str | None,

View on GitHub (pinned to f4587218dd)

Solutions

  1. Reduce the dataset SQL to a single SELECT statement (combine parts with CTEs or subqueries).
  2. Remove trailing semicolon-separated helper statements (e.g. SET statements) — put them in the database session or engine options instead.
  3. If you need multiple outputs, create one dataset per statement.

Example fix

-- before
SELECT id, total FROM orders_2023;
SELECT id, total FROM orders_2024;

-- after
SELECT id, total FROM orders_2023
UNION ALL
SELECT id, total FROM orders_2024
Defensive patterns

Strategy: validation

Validate before calling

def is_single_statement(sql: str, engine: str) -> bool:
    try:
        return len(SQLScript(sql, engine=engine).statements) == 1
    except SupersetParseError:
        return False

Try / catch

try:
    get_virtual_table_metadata(dataset)
except SupersetSecurityException as ex:
    if 'single queries' in str(ex):
        # merge statements with CTEs/UNION and retry once
        ...

Prevention

When it happens

Trigger: Dataset SQL like `SELECT ...; SELECT ...` or a SELECT followed by any second statement (including a trailing temp-table creation or a comment-only statement the parser counts). Evaluated as `len(parsed_script.statements) > 1` after rendering.

Common situations: Pasting a multi-statement SQL Lab script into 'Save as dataset'; CTE-plus-.final-select patterns that include an extra trailing statement; SQL copied from a notebook cell with several statements.

Related errors


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