getredash/redash · info · InterruptException

Query cancelled by user.

Error message

Query cancelled by user.

What it means

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.

Source

Thrown at redash/query_runner/duckdb.py:111

                        raise Exception("Unknown extension prefix.")
                else:
                    self.con.execute(f"INSTALL {ext}")
                    self.con.execute(f"LOAD {ext}")
            except Exception as e:
                logger.warning("Failed to load extension %s: %s", ext, e)

    def run_query(self, query, user) -> tuple:
        try:
            cursor = self.con.cursor()
            cursor.execute(query)
            columns = self.fetch_columns(
                [(d[0], TYPES_MAP.get(d[1].upper(), TYPE_STRING)) for d in cursor.description]
            )
            rows = [dict(zip((col["name"] for col in columns), row)) for row in cursor.fetchall()]
            data = {"columns": columns, "rows": rows}
            return data, None
        except duckdb.InterruptException:
            raise InterruptException("Query cancelled by user.")
        except Exception as e:
            logger.exception("Error running query: %s", e)
            return None, str(e)

    def get_schema(self, get_stats=False) -> list:
        tables_query = """
            SELECT table_catalog, table_schema, table_name FROM information_schema.tables
            WHERE table_schema NOT IN ('information_schema', 'pg_catalog');
        """
        tables_results, error = self.run_query(tables_query, None)
        if error:
            raise Exception(f"Failed to get tables: {error}")

        schema = {}
        for table_row in tables_results["rows"]:
            # Include catalog (database) in the full table name for MotherDuck support
            catalog = table_row["table_catalog"]
            schema_name = table_row["table_schema"]

View on GitHub (pinned to ca79fe988d)

Solutions

  1. No query fix needed — it means the cancellation worked as intended
  2. If cancellations are accidental, avoid duplicate Cancel clicks and stale tabs
  3. Tune long queries (filters, LIMIT, materialized intermediates) so cancellation isn't needed
  4. Re-run the query when ready; Redash marks the execution as cancelled
Defensive patterns

Strategy: try-catch

Validate before calling

# interruption is user-initiated; only preflight DB reachability
_, err = runner.run_query('SELECT 1', None)

Type guard

def was_user_cancelled(exc: Exception) -> bool:
    return 'cancelled by user' in str(exc) or type(exc).__name__ == 'InterruptException'

Try / catch

try:
    data, err = runner.run_query(q, u)
except Exception as e:
    if 'cancelled by user' in str(e):
        mark_execution_cancelled(); return  # not alert-worthy

Prevention

When it happens

Trigger: 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.

Common situations: Cancelling long-running analytics queries, server-side timeouts cancelling queries, or worker shutdowns during execution.

Related errors


AI-assisted analysis of getredash/redash@ca79fe988d (2026-08-28). Data as JSON: /api/errors/de073844d58495ef. Report an issue: GitHub.