{"record":{"id":"65f0a1b9a768796d","repo":"apache/superset","slug":"dml-not-allowed-error","errorCode":"DML_NOT_ALLOWED_ERROR","errorMessage":"This database does not allow for DDL/DML, but the query mutates data. Please contact your administrator for more assistance.","messagePattern":"This database does not allow for DDL/DML, but the query mutates data\\. Please contact your administrator for more assistance\\.","errorType":"exception","errorClass":"SupersetDMLNotAllowedException","httpStatus":500,"severity":"error","filePath":"superset/commands/sql_lab/estimate.py","lineNumber":150,"sourceCode":"            resolved_schema = self._database.resolve_query_default_schema(\n                self._sql, self._schema, catalog, self._template_params\n            )\n            # An explicit schema still wins for matching/RLS targeting; otherwise\n            # fall back to the runtime-resolved default.\n            effective_schema = self._schema or resolved_schema or \"\"\n\n        if disallowed_tables:\n            # Honors schema-qualified denylist entries (e.g.\n            # ``information_schema.tables``) and reports only the tables\n            # actually referenced by the query.\n            found_tables = parsed_script.get_disallowed_tables(\n                disallowed_tables, effective_schema\n            )\n            if found_tables:\n                raise SupersetDisallowedSQLTableException(found_tables)\n\n        if parsed_script.has_mutation() and not self._database.allow_dml:\n            raise SupersetDMLNotAllowedException()\n\n        if rls_enabled:\n            for statement in parsed_script.statements:\n                apply_rls(self._database, catalog, effective_schema, statement)\n            return parsed_script.format()\n\n        return sql\n\n    def run(\n        self,\n    ) -> list[dict[str, Any]]:\n        self.validate()\n\n        sql = self._sql\n        if self._template_params:\n            # Access is already checked in validate() before any rendering.\n            template_processor = get_template_processor(self._database)\n            try:","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/commands/sql_lab/estimate.py#L132-L168","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Only estimate SELECT queries on this database, or enable 'Allow DML' in the database settings if mutation is intended (operator decision)","Move DML statements to a database connection where allow_dml is true","Check GET /api/v1/database/{id} allow_dml field before offering the estimate action in tooling"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"db = DatabaseDAO.find_by_id(database_id)\nif query_mutates(sql) and not db.allow_dml:\n    raise ValueError(\"this database disallows DDL/DML; estimate only SELECTs\")","typeGuard":null,"tryCatchPattern":"try:\n    EstimateQueryCostCommand(params).run()\nexcept SupersetDMLNotAllowedException:\n    # route the mutation to a DML-enabled database or drop the estimate request","preventionTips":["Check the database's allow_dml flag before offering cost estimation for DML","The gate applies to estimation too, by design — do not try to bypass it"],"tags":["sql-lab","dml","security","query-cost","database-config"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}