{"record":{"id":"de073844d58495ef","repo":"getredash/redash","slug":"query-cancelled-by-user","errorCode":null,"errorMessage":"Query cancelled by user.","messagePattern":"Query cancelled by user\\.","errorType":"exception","errorClass":"InterruptException","httpStatus":null,"severity":"info","filePath":"redash/query_runner/duckdb.py","lineNumber":111,"sourceCode":"                        raise Exception(\"Unknown extension prefix.\")\n                else:\n                    self.con.execute(f\"INSTALL {ext}\")\n                    self.con.execute(f\"LOAD {ext}\")\n            except Exception as e:\n                logger.warning(\"Failed to load extension %s: %s\", ext, e)\n\n    def run_query(self, query, user) -> tuple:\n        try:\n            cursor = self.con.cursor()\n            cursor.execute(query)\n            columns = self.fetch_columns(\n                [(d[0], TYPES_MAP.get(d[1].upper(), TYPE_STRING)) for d in cursor.description]\n            )\n            rows = [dict(zip((col[\"name\"] for col in columns), row)) for row in cursor.fetchall()]\n            data = {\"columns\": columns, \"rows\": rows}\n            return data, None\n        except duckdb.InterruptException:\n            raise InterruptException(\"Query cancelled by user.\")\n        except Exception as e:\n            logger.exception(\"Error running query: %s\", e)\n            return None, str(e)\n\n    def get_schema(self, get_stats=False) -> list:\n        tables_query = \"\"\"\n            SELECT table_catalog, table_schema, table_name FROM information_schema.tables\n            WHERE table_schema NOT IN ('information_schema', 'pg_catalog');\n        \"\"\"\n        tables_results, error = self.run_query(tables_query, None)\n        if error:\n            raise Exception(f\"Failed to get tables: {error}\")\n\n        schema = {}\n        for table_row in tables_results[\"rows\"]:\n            # Include catalog (database) in the full table name for MotherDuck support\n            catalog = table_row[\"table_catalog\"]\n            schema_name = table_row[\"table_schema\"]","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/getredash/redash/blob/ca79fe988d81cdac9675b412f3dfcab107bc1fbc/redash/query_runner/duckdb.py#L93-L129","documentation":"DuckDB runner maps duckdb.InterruptException — raised when the client interrupts a running query — to its own InterruptException('Query cancelled by user.'), signaling user-initiated cancellation rather than a query defect.","triggerScenarios":"A user hits Cancel in the Redash UI (or the worker is interrupted) while a DuckDB/MotherDuck query executes, causing duckdb to raise InterruptException mid-execution.","commonSituations":"Cancelling long-running analytics queries, server-side timeouts cancelling queries, or worker shutdowns during execution.","solutions":["No query fix needed — it means the cancellation worked as intended","If cancellations are accidental, avoid duplicate Cancel clicks and stale tabs","Tune long queries (filters, LIMIT, materialized intermediates) so cancellation isn't needed","Re-run the query when ready; Redash marks the execution as cancelled"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"# interruption is user-initiated; only preflight DB reachability\n_, err = runner.run_query('SELECT 1', None)","typeGuard":"def was_user_cancelled(exc: Exception) -> bool:\n    return 'cancelled by user' in str(exc) or type(exc).__name__ == 'InterruptException'","tryCatchPattern":"try:\n    data, err = runner.run_query(q, u)\nexcept Exception as e:\n    if 'cancelled by user' in str(e):\n        mark_execution_cancelled(); return  # not alert-worthy","preventionTips":["Don't classify cancellations as failures in alerting rules","Guard the Cancel button against double-clicks in custom UIs","Tune long queries so cancellation is rarely needed"],"tags":["redash","duckdb","query-cancellation"],"backgroundTag":"query-cancelled","analyzedSha":"ca79fe988d81cdac9675b412f3dfcab107bc1fbc","analyzedAt":"2026-08-28T18:32:34.637Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}