apache/superset · error · SupersetDMLNotAllowedException

DML_NOT_ALLOWED_ERROR

DML_NOT_ALLOWED_ERROR

Error message

This database does not allow for DDL/DML, but the query mutates data. Please contact your administrator for more assistance.

What it means

Raised in EstimateQueryCostCommand preprocessing (superset/commands/sql_lab/estimate.py:150) as SupersetDMLNotAllowedException when parsed_script.has_mutation() is true and the database record has allow_dml = false. Estimation deliberately runs the same DML guard as execution: even though estimating a mutation does not execute it, the gate blocks the request. SupersetErrorType.DML_NOT_ALLOWED_ERROR.

Source

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

            resolved_schema = self._database.resolve_query_default_schema(
                self._sql, self._schema, catalog, self._template_params
            )
            # An explicit schema still wins for matching/RLS targeting; otherwise
            # fall back to the runtime-resolved default.
            effective_schema = self._schema or resolved_schema or ""

        if disallowed_tables:
            # Honors schema-qualified denylist entries (e.g.
            # ``information_schema.tables``) and reports only the tables
            # actually referenced by the query.
            found_tables = parsed_script.get_disallowed_tables(
                disallowed_tables, effective_schema
            )
            if found_tables:
                raise SupersetDisallowedSQLTableException(found_tables)

        if parsed_script.has_mutation() and not self._database.allow_dml:
            raise SupersetDMLNotAllowedException()

        if rls_enabled:
            for statement in parsed_script.statements:
                apply_rls(self._database, catalog, effective_schema, statement)
            return parsed_script.format()

        return sql

    def run(
        self,
    ) -> list[dict[str, Any]]:
        self.validate()

        sql = self._sql
        if self._template_params:
            # Access is already checked in validate() before any rendering.
            template_processor = get_template_processor(self._database)
            try:

View on GitHub (pinned to f4587218dd)

Solutions

  1. Only estimate SELECT queries on this database, or enable 'Allow DML' in the database settings if mutation is intended (operator decision)
  2. Move DML statements to a database connection where allow_dml is true
  3. Check GET /api/v1/database/{id} allow_dml field before offering the estimate action in tooling
Defensive patterns

Strategy: validation

Validate before calling

db = DatabaseDAO.find_by_id(database_id)
if query_mutates(sql) and not db.allow_dml:
    raise ValueError("this database disallows DDL/DML; estimate only SELECTs")

Try / catch

try:
    EstimateQueryCostCommand(params).run()
except SupersetDMLNotAllowedException:
    # route the mutation to a DML-enabled database or drop the estimate request

Prevention

When it happens

Trigger: Submitting INSERT/UPDATE/DELETE/CREATE/ALTER/TRUNCATE (or other mutating statements sqlscriptbox detects) for cost estimation on a database whose settings have 'Allow DML' unchecked.

Common situations: Users trying to preview the cost of a data-change script on a read-only connection; admins disabling DML on production databases and users not realizing the estimate path enforces the same policy.

Related errors


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