apache/superset · error · SupersetDisallowedSQLFunctionException

SYNTAX_ERROR

SYNTAX_ERROR

Error message

SQL statement contains disallowed function(s): {functions}

What it means

Raised in the SQL preprocessing inside EstimateQueryCostCommand (superset/commands/sql_lab/estimate.py:112) as SupersetDisallowedSQLFunctionException when sqlscriptbox's SQLScript.check_functions_present() finds any function from the engine's DISALLOWED_SQL_FUNCTIONS config set in the submitted SQL. Cost estimation applies the same security controls as execution, so the estimator is intentionally blocked before reaching the database. Classified under SupersetErrorType.SYNTAX_ERROR.

Source

Thrown at superset/commands/sql_lab/estimate.py:112

    def _apply_sql_security(self, sql: str) -> str:
        """Run the disallowed-function/table, DML and RLS controls against the
        SQL to be estimated, mirroring ``sql_lab.execute_sql_statements``.

        Returns the SQL with RLS predicates injected (when ``RLS_IN_SQLLAB`` is
        enabled), so the cost estimate reflects the same constrained query the
        user would actually be allowed to run.
        """
        db_engine_spec = self._database.db_engine_spec
        parsed_script = SQLScript(sql, engine=db_engine_spec.engine)

        disallowed_functions = app.config["DISALLOWED_SQL_FUNCTIONS"].get(
            db_engine_spec.engine,
            set(),
        )
        if disallowed_functions and parsed_script.check_functions_present(
            disallowed_functions
        ):
            raise SupersetDisallowedSQLFunctionException(disallowed_functions)

        disallowed_tables = app.config["DISALLOWED_SQL_TABLES"].get(
            db_engine_spec.engine,
            set(),
        )
        rls_enabled = is_feature_enabled("RLS_IN_SQLLAB")

        # Resolve the effective per-query schema once, the same way the execution
        # path does (``sql_lab.execute_sql_statements``), but only when a control
        # below actually needs it. Going through ``get_default_schema_for_query``
        # rather than the static ``get_default_schema`` runs engine-specific
        # per-query security gates too — e.g. ``PostgresEngineSpec`` rejects a
        # query that sets ``search_path`` — and resolves unqualified references to
        # the schema the engine uses at runtime, so both the denylist check and
        # RLS injection match the execution path exactly.
        catalog: str | None = None
        effective_schema = ""
        if disallowed_tables or rls_enabled:

View on GitHub (pinned to f4587218dd)

Solutions

  1. Remove the disallowed function(s) from the SQL — the exception reports exactly which functions were found
  2. Check superset_config.py DISALLOWED_SQL_FUNCTIONS for the engine in question to know what is banned
  3. If the function is legitimately needed, ask the administrator to remove it from the denylist (an operator decision, not a code fix)

Example fix

-- before (DISALLOWED_SQL_FUNCTIONS contains pg_sleep for postgres)
SELECT pg_sleep(10), * FROM accounts;

-- after
SELECT * FROM accounts;
Defensive patterns

Strategy: try-catch

Validate before calling

# client-side pre-check: know the denylist for the engine
DISALLOWED = {"pg_sleep", "pg_read_file"}  # mirror of DISALLOWED_SQL_FUNCTIONS['postgresql']
used = extract_function_names(sql)
violations = used & DISALLOWED
if violations:
    raise ValueError(f"remove disallowed functions: {sorted(violations)}")

Try / catch

try:
    EstimateQueryCostCommand(params).run()
except SupersetDisallowedSQLFunctionException as ex:
    # ex lists the disallowed functions found; strip them from the SQL and retry

Prevention

When it happens

Trigger: Estimating cost for SQL that calls a function listed in DISALLOWED_SQL_FUNCTIONS[engine] in superset_config.py — commonly things like sleep-like or filesystem functions; the denylist is engine-specific (keyed by db_engine_spec.engine).

Common situations: Operators add functions to DISALLOWED_SQL_FUNCTIONS to prevent DoS or data exfiltration, then users' previously estimable queries start failing; porting queries between engines with different denylists.

Related errors


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