Skip to content

Commit caa5d04

Browse files
committed
fix: Set results before running task to avoid UnboundLocalError
dbt handles exceptions raised by task.run() with the track_run context manager. We are also doing the same thing. The problem is that some exceptions, like FailedToConnectException, are failing silently (at least for us, CLI users do see a log) and are not re-raised by dbt. Continuing with execution would lead to an UnboundLocalError as we don't account for results never being set. To address this we preemptively set results to None before running a task.
1 parent e97e1c2 commit caa5d04

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

airflow_dbt_python/hooks/dbt.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,8 @@ def run_dbt_task(self, config: BaseConfig) -> tuple[bool, Optional[RunResult]]:
572572
# before deps runs and the following would raise a CompilationError.
573573
runtime_config.load_dependencies()
574574

575+
results = None
576+
575577
with adapter_management():
576578
register_adapter(runtime_config)
577579

tests/hooks/dbt/test_dbt_run.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,42 @@ def test_dbt_run_task_compiled(
149149
for index, result in enumerate(results.results, start=2):
150150
assert result.status == RunStatus.Success
151151
assert result.node.unique_id == f"model.test.model_{index}"
152+
153+
154+
def test_dbt_run_task_that_fails_to_connect(
155+
hook, profiles_file, dbt_project_file, model_files
156+
):
157+
"""
158+
Test a dbt run task while failing to connect.
159+
160+
As dbt handles exceptions with track_run, we need to ensure we don't fail when
161+
dbt is not bubbling up exceptions. In particular, FailedToConnectException is not
162+
re-raised.
163+
"""
164+
factory = hook.get_config_factory("run")
165+
config = factory.create_config(
166+
project_dir=dbt_project_file.parent,
167+
profiles_dir=profiles_file.parent,
168+
)
169+
170+
def create_fake_task():
171+
task = config.dbt_task.from_args(config)
172+
173+
def run():
174+
from dbt.exceptions import FailedToConnectException
175+
176+
raise FailedToConnectException("I failed")
177+
178+
def interpret_results(*args):
179+
return False
180+
181+
task.run = run
182+
task.interpret_results = interpret_results
183+
return task
184+
185+
config.create_dbt_task = create_fake_task
186+
187+
success, results = hook.run_dbt_task(config)
188+
189+
assert success is False
190+
assert results is None

0 commit comments

Comments
 (0)