Skip to content

fix(sql-lab): raise SupersetTemplateException instead of raw UndefinedError in SQLExecutor.execute_async - #42851

Open
eschutho wants to merge 1 commit into
masterfrom
fix-jinja-undefined-execute-async
Open

fix(sql-lab): raise SupersetTemplateException instead of raw UndefinedError in SQLExecutor.execute_async#42851
eschutho wants to merge 1 commit into
masterfrom
fix-jinja-undefined-execute-async

Conversation

@eschutho

@eschutho eschutho commented Aug 6, 2026

Copy link
Copy Markdown
Member

SUMMARY

SQLExecutor._render_sql_template() (superset/sql/execution/executor.py) called tp.process_template() with no try/except at all. process_template() can leak a raw jinja2.exceptions.UndefinedError for a template referencing an undefined variable that isn't called as a function. execute() happens to be safe because its whole body is wrapped in a broad except Exception, but execute_async() has no such guard — the raw exception propagated straight out of the public Database.execute_async() API contract.

PROBLEM

superset/jinja_context.py::BaseTemplateProcessor.process_template() converts most Jinja rendering failures into typed exceptions, but has a bare-raise fallback for UndefinedError when the undefined variable is accessed via attribute/subscript syntax rather than a function call. This is the same gap already fixed at other process_template() call sites in this codebase: #42366, #42401, #42714, #42757, #42802 — this PR fixes it at a new call site.

_render_sql_template() is shared by both SQLExecutor.execute() and SQLExecutor.execute_async(). execute()'s entire body (including the _prepare_sql() call that reaches _render_sql_template()) is wrapped in try: ... except Exception as ex: return self._create_error_result(...), so any exception raised there already degrades gracefully into a QueryResult(status=FAILED) — not a bug. execute_async() has no equivalent guard around its _prepare_sql() call; confirmed empirically that database.execute_async("SELECT {{ missing_var[0] }}", options=QueryOptions(template_params={"foo": "bar"})) raised a bare jinja2.exceptions.UndefinedError on master, not any SupersetException. This also breaks the method's own established contract: execute_async() already raises typed SupersetSecurityException for other prep-time failures (e.g. disallowed DML), so callers reasonably expect prep-time errors to always be Superset exceptions.

FIX

Wrapped the process_template() call inside _render_sql_template() in try/except TemplateError as ex: raise SupersetTemplateException(str(ex)) from ex. Reused the existing SupersetTemplateException (status 422) rather than inventing a new exception class — it's already the established general-purpose Superset exception for Jinja template rendering failures elsewhere in this codebase (jinja_context.py itself raises it for RecursionError, and it's caught in superset/datasets/api.py and superset/commands/database/validate_sql.py).

Additive-only: no behavior change to the sync execute() path (its broad except Exception still catches the now-typed exception and returns the same QueryResult(FAILED) shape — only the error message text improves).

TESTING INSTRUCTIONS

Added two tests to tests/unit_tests/sql/execution/test_executor.py:

  • test_execute_async_undefined_template_var_raises_superset_template_exception — asserts execute_async() with a template referencing an undefined variable raises SupersetTemplateException, not a raw jinja2.exceptions.UndefinedError.

  • test_execute_sync_undefined_template_var_returns_failed_result — guard that the sync execute() path's error-handling contract (returns QueryResult(status=FAILED)) is unchanged.

  • Confirmed the regression test fails on pre-fix code: checked out the pre-fix version of executor.py (test kept), reran — the async test fails with the raw jinja2.exceptions.UndefinedError escaping uncaught.

  • Post-fix: full tests/unit_tests/sql/execution/test_executor.py passes (82/82).

  • ruff check / ruff format --check: pass on both changed files.

ADDITIONAL INFORMATION

  • Has associated tests
  • Confirmed the regression test fails on pre-fix code and passes post-fix

Tradeoffs: none — additive-only exception-handling fix, no behavior change to any currently-working path.

Related: #42366, #42401, #42714, #42757, #42802 (same process_template() bare-raise-fallback bug class, different call sites).

…dError in SQLExecutor.execute_async

_render_sql_template() called process_template() with no try/except, so a
Jinja UndefinedError for an undefined variable not called as a function
would leak raw past execute_async() (execute() already caught it via its
broad except Exception). Wrap the call and re-raise as
SupersetTemplateException, consistent with how process_template() itself
already handles this failure mode elsewhere.
@dosubot dosubot Bot added global:jinja Related to Jinja templating sqllab Namespace | Anything related to the SQL Lab labels Aug 6, 2026
@bito-code-review

bito-code-review Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #840521

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: 4a24fb5..4a24fb5
    • superset/sql/execution/executor.py
    • tests/unit_tests/sql/execution/test_executor.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

Comment on lines +764 to +767
try:
return tp.process_template(sql, **template_params)
except TemplateError as ex:
raise SupersetTemplateException(str(ex)) from ex

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The broad TemplateError catch flattens compilation-time TemplateSyntaxError exceptions raised by direct-rendering processors such as Spark and Trino into a generic SupersetTemplateException, discarding the structured SupersetSyntaxErrorException/SupersetError details that the standard processor provides. Preserve the existing typed syntax-error mapping before applying the fallback wrapper for raw render-time errors. [api mismatch]

Severity Level: Major ⚠️
- ⚠️ Spark and Trino template syntax errors lose line metadata.
- ⚠️ API responses lose structured syntax-error classification.
- ⚠️ SQL Lab users receive less actionable template diagnostics.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset/sql/execution/executor.py
**Line:** 764:767
**Comment:**
	*Api Mismatch: The broad `TemplateError` catch flattens compilation-time `TemplateSyntaxError` exceptions raised by direct-rendering processors such as Spark and Trino into a generic `SupersetTemplateException`, discarding the structured `SupersetSyntaxErrorException`/`SupersetError` details that the standard processor provides. Preserve the existing typed syntax-error mapping before applying the fallback wrapper for raw render-time errors.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

@bito-code-review

Copy link
Copy Markdown
Contributor

The review suggestion is correct. The current implementation in superset/sql/execution/executor.py catches TemplateError and wraps it in a generic SupersetTemplateException, which loses specific error details (like SupersetSyntaxErrorException) that might be provided by the template processor. To resolve this, you should catch specific syntax-related exceptions first and only fall back to the generic SupersetTemplateException for other rendering errors.

superset/sql/execution/executor.py

try:
            return tp.process_template(sql, **template_params)
        except SupersetSyntaxErrorException:
            raise
        except TemplateError as ex:
            raise SupersetTemplateException(str(ex)) from ex

@codecov

codecov Bot commented Aug 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 20.00000% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 65.73%. Comparing base (ba09f39) to head (4a24fb5).
⚠️ Report is 6 commits behind head on master.

Files with missing lines Patch % Lines
superset/sql/execution/executor.py 20.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #42851      +/-   ##
==========================================
- Coverage   65.73%   65.73%   -0.01%     
==========================================
  Files        2843     2843              
  Lines      162659   162670      +11     
  Branches    37239    37239              
==========================================
+ Hits       106927   106930       +3     
- Misses      53640    53648       +8     
  Partials     2092     2092              
Flag Coverage Δ
hive 38.00% <20.00%> (-0.01%) ⬇️
mysql 57.80% <20.00%> (-0.01%) ⬇️
postgres 57.84% <20.00%> (-0.01%) ⬇️
presto 39.92% <20.00%> (-0.01%) ⬇️
python 59.21% <20.00%> (-0.01%) ⬇️
sqlite 57.47% <20.00%> (-0.01%) ⬇️
unit 100.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

global:jinja Related to Jinja templating size/M sqllab Namespace | Anything related to the SQL Lab

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant