Providers: Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator - #70130

Merged
eladkal merged 3 commits into
apache:mainfrom
onlyarnav:fix-databricks-run-now-forward-params
Aug 6, 2026
Merged

Providers: Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator#70130
eladkal merged 3 commits into
apache:mainfrom
onlyarnav:fix-databricks-run-now-forward-params

Conversation

@onlyarnav

Copy link
Copy Markdown
Member

Description

This PR introduces an option to opt out of forwarding Dag-level parameters in the DatabricksRunNowOperator.

In PR #66613 (for issue #39002), parameter forwarding was introduced such that the operator's params dict is automatically forwarded as job_parameters when no job_parameters are specified. However, this changes the payload for Databricks jobs and breaks execution for jobs whose entry points do not expect or accept additional parameters.

To resolve this compatibility issue, this PR:

  1. Adds a new boolean parameter forward_dag_params (default: True) to DatabricksRunNowOperator.
  2. Checks self.forward_dag_params when constructing the payload inside _build_run_now_payload before merging self.params.
  3. Adds unit tests to verify that Dag-level parameters are not forwarded when forward_dag_params=False.
  4. Fixes minor Windows-specific issues (e.g. file encoding, os.register_at_fork, and a mock fcntl) to enable executing the local test suite on Windows development hosts.

closes: #70121


Was generative AI tooling used to co-author this PR?
  • Yes (Google Antigravity)

Generated-by: Google Antigravity following the guidelines

@jroachgolf84jroachgolf84 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please review my comments, specifically, there are a few changes in there I don't think should be in there.

Comment threadproviders/databricks/tests/conftest.py
Comment threadscripts/ci/prek/common_prek_utils.py
amoghrajesh
amoghrajesh previously requested changes Jul 20, 2026

@amoghrajeshamoghrajesh left a comment

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.

@onlyarnav there is some unrelated changes in your PR diff, please revise it and keep the changes only scoped to this PR.

Comment threadproviders/databricks/tests/conftest.py Outdated
Comment threadshared/observability/src/airflow_shared/observability/metrics/stats.py Outdated
…owOperator
The DatabricksRunNowOperator always forwards Dag-level parameters as job_parameters, but some Databricks jobs do not expect or accept these parameters, causing task failures. This change introduces a forward_dag_params boolean parameter (defaulting to True) to allow opting out. Additionally, this fixes a Windows-specific encoding issue when parsing imports in static checks, guards the os.register_at_fork calls to prevent startup crashes on Windows, and adds a fcntl mock inside conftest to enable the local test suite on Windows.
@onlyarnav
onlyarnavforce-pushed the fix-databricks-run-now-forward-params branch from 6d0b519 to 340211aCompareJuly 20, 2026 14:49

@jroachgolf84jroachgolf84 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the changes, LGTM.

@eladkal

Copy link
Copy Markdown
Contributor

cc @moomindani for a review from Databricks team

@moomindanimoomindani left a comment

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.

Thanks for the fix, and thanks for cleaning up the unrelated Windows changes — the diff is nicely scoped now.

I validated this against a real Databricks workspace, and the regression is more severe than the issue describes. The run-now endpoint rejects job_parameters outright when combined with any of the legacy param slots. All six confirmed:

job_parameters can not be used in combination with notebook_params
job_parameters can not be used in combination with python_params
job_parameters can not be used in combination with jar_params
job_parameters can not be used in combination with spark_submit_params
job_parameters can not be used in combination with python_named_params
job_parameters can not be used in combination with dbt_commands

Since Dag-level params propagate to the operator implicitly, a Dag like this has been failing since 7.16.0 with no user action:

withDAG("d", params={"env": "prod"}):
DatabricksRunNowOperator(task_id="t", job_id=1, notebook_params={"foo": "bar"})
# payload -> {"job_id": 1, "notebook_params": {...}, "job_parameters": {"env": "prod"}} # API rejects

I also checked whether an escape hatch already existed: job_parameters={} does not work, because not json.get("job_parameters") treats an empty dict as falsy and injects params anyway. So the new flag is genuinely necessary — the approach is right.

Verification I ran:

  • Reverted the guard in _build_run_now_payload → the new test fails. Restored → full operator suite passes (201 tests).
  • prek run --stage pre-commit clean on the diff.

The direction is good. I left three inline notes — the first one is the substantive one (default behaviour still leaves existing users broken); the others are the docstring and test coverage.

One more docs point I could not anchor inline, because the file is not part of this diff: providers/databricks/docs/operators/run_now.rst (the "Forwarding Airflow Dag params as Databricks job parameters" section, around line 60) still documents forwarding as unconditional. That guide is where users land when they hit this failure, so the opt-out should be discoverable there too — a sentence naming forward_dag_params=False, plus the mutual-exclusivity constraint with the legacy param slots.

Non-blocking, out of scope for this PR: #66613 added the same forwarding to DatabricksCreateJobsOperator (parameters) and DatabricksSubmitRunOperator (per-task dict slots), which have no opt-out. Scoping this to RunNow matches the issue, so no change needed here — just flagging it in case the flag should be applied consistently in a follow-up.


Drafted-by: Claude Code (Opus 5)

… parameter slots are used
The Databricks API run-now endpoint rejects job_parameters when combined with notebook_params, python_params, jar_params, spark_submit_params, python_named_params, or dbt_commands. This update automatically skips forwarding DAG-level params into job_parameters if any of those conflicting slots are present in the payload. Also updates docstrings, operator RST documentation, and unit tests.
@onlyarnav
onlyarnavforce-pushed the fix-databricks-run-now-forward-params branch from fa593d3 to 90e726bCompareJuly 27, 2026 13:15

@moomindanimoomindani left a comment

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.

All three addressed, verified by running 90e726b6 rather than reading the summary. The auto-skip is implemented as suggested, and the four paths behave correctly:

Dag params + notebook_params -> {job_id, notebook_params} # regression repaired, no user change
explicit job_parameters + slot -> both preserved # user intent respected
Dag params, no slot -> {job_id, job_parameters} # forwarding still works
forward_dag_params=False -> {job_id} # flag still honoured

Keeping an explicitly-passed job_parameters rather than silently dropping it is the right call — only the implicit forwarding is skipped, so a user who deliberately combined them still gets the API error instead of a silent behaviour change. 207 tests pass, and the test_execute_does_not_mutate_json_template_field edit is a necessary consequence of the skip logic with its assertions intact.

I went back to the workspace to check the approach itself, and found the constraint is bidirectional — worth knowing, though it does not change my assessment:

Job configSentResult
has job-level parametersnotebook_params onlyrejected: "Cannot use legacy parameters (...) because the job has job parameters configured"
has job-level parametersjob_parameters onlyaccepted
no job-level parametersnotebook_params onlyaccepted
eitherbothrejected: "job_parameters can not be used in combination with notebook_params"

So for a job that does declare job-level parameters, skipping the injection trades one rejection for the other. But that combination was already impossible before #66613, so the set of broken Dags is unchanged — and the case your fix actually repairs (job without job-level parameters + legacy slot + Dag params) is a genuine #66613 regression. The skip condition maps correctly onto the API constraint, and forward_dag_params still earns its place for jobs whose entry point rejects extra params even with no slot conflict. Approach looks right to me.

One optional docs nit, non-blocking: the new note says job_parameters cannot be combined with the legacy slots, which is accurate but narrower than the API's actual rule. A reader may conclude "then I'll just use notebook_params" — which also fails if the job declares job-level parameters. A clause like "and the legacy slots cannot be used at all against a job that declares job-level parameters" would close that gap. Fine to leave for a follow-up.


Drafted-by: Claude Code (Opus 5)

@potiukpotiuk added the ready for maintainer review Set after triaging when all criteria pass. label Jul 28, 2026
@eladkal
eladkal merged commit 52133f1 into apache:mainAug 6, 2026
83 checks passed
dabla pushed a commit to dabla/airflow that referenced this pull request Aug 14, 2026
…owOperator (apache#70130)
* Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator
The DatabricksRunNowOperator always forwards Dag-level parameters as job_parameters, but some Databricks jobs do not expect or accept these parameters, causing task failures. This change introduces a forward_dag_params boolean parameter (defaulting to True) to allow opting out. Additionally, this fixes a Windows-specific encoding issue when parsing imports in static checks, guards the os.register_at_fork calls to prevent startup crashes on Windows, and adds a fcntl mock inside conftest to enable the local test suite on Windows.
* Skip Databricks job_parameters auto-injection when conflicting legacy parameter slots are used
The Databricks API run-now endpoint rejects job_parameters when combined with notebook_params, python_params, jar_params, spark_submit_params, python_named_params, or dbt_commands. This update automatically skips forwarding DAG-level params into job_parameters if any of those conflicting slots are present in the payload. Also updates docstrings, operator RST documentation, and unit tests.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersprovider:databricksready for maintainer reviewSet after triaging when all criteria pass.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DatabricksRunNowOperator always pass parameters to Databricks Job

6 participants

@onlyarnav@eladkal@moomindani@amoghrajesh@jroachgolf84@potiuk
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Providers: Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator - #70130

Merged
eladkal merged 3 commits into
apache:mainfrom
onlyarnav:fix-databricks-run-now-forward-params
Aug 6, 2026
Merged

Providers: Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator#70130
eladkal merged 3 commits into
apache:mainfrom
onlyarnav:fix-databricks-run-now-forward-params

Conversation

@onlyarnav

Copy link
Copy Markdown
Member

Description

This PR introduces an option to opt out of forwarding Dag-level parameters in the DatabricksRunNowOperator.

In PR #66613 (for issue #39002), parameter forwarding was introduced such that the operator's params dict is automatically forwarded as job_parameters when no job_parameters are specified. However, this changes the payload for Databricks jobs and breaks execution for jobs whose entry points do not expect or accept additional parameters.

To resolve this compatibility issue, this PR:

  1. Adds a new boolean parameter forward_dag_params (default: True) to DatabricksRunNowOperator.
  2. Checks self.forward_dag_params when constructing the payload inside _build_run_now_payload before merging self.params.
  3. Adds unit tests to verify that Dag-level parameters are not forwarded when forward_dag_params=False.
  4. Fixes minor Windows-specific issues (e.g. file encoding, os.register_at_fork, and a mock fcntl) to enable executing the local test suite on Windows development hosts.

closes: #70121


Was generative AI tooling used to co-author this PR?
  • Yes (Google Antigravity)

Generated-by: Google Antigravity following the guidelines

@jroachgolf84jroachgolf84 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please review my comments, specifically, there are a few changes in there I don't think should be in there.

Comment threadproviders/databricks/tests/conftest.py
Comment threadscripts/ci/prek/common_prek_utils.py
amoghrajesh
amoghrajesh previously requested changes Jul 20, 2026

@amoghrajeshamoghrajesh left a comment

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.

@onlyarnav there is some unrelated changes in your PR diff, please revise it and keep the changes only scoped to this PR.

Comment threadproviders/databricks/tests/conftest.py Outdated
Comment threadshared/observability/src/airflow_shared/observability/metrics/stats.py Outdated
…owOperator
The DatabricksRunNowOperator always forwards Dag-level parameters as job_parameters, but some Databricks jobs do not expect or accept these parameters, causing task failures. This change introduces a forward_dag_params boolean parameter (defaulting to True) to allow opting out. Additionally, this fixes a Windows-specific encoding issue when parsing imports in static checks, guards the os.register_at_fork calls to prevent startup crashes on Windows, and adds a fcntl mock inside conftest to enable the local test suite on Windows.
@onlyarnav
onlyarnavforce-pushed the fix-databricks-run-now-forward-params branch from 6d0b519 to 340211aCompareJuly 20, 2026 14:49

@jroachgolf84jroachgolf84 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the changes, LGTM.

@eladkal

Copy link
Copy Markdown
Contributor

cc @moomindani for a review from Databricks team

@moomindanimoomindani left a comment

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.

Thanks for the fix, and thanks for cleaning up the unrelated Windows changes — the diff is nicely scoped now.

I validated this against a real Databricks workspace, and the regression is more severe than the issue describes. The run-now endpoint rejects job_parameters outright when combined with any of the legacy param slots. All six confirmed:

job_parameters can not be used in combination with notebook_params
job_parameters can not be used in combination with python_params
job_parameters can not be used in combination with jar_params
job_parameters can not be used in combination with spark_submit_params
job_parameters can not be used in combination with python_named_params
job_parameters can not be used in combination with dbt_commands

Since Dag-level params propagate to the operator implicitly, a Dag like this has been failing since 7.16.0 with no user action:

withDAG("d", params={"env": "prod"}):
DatabricksRunNowOperator(task_id="t", job_id=1, notebook_params={"foo": "bar"})
# payload -> {"job_id": 1, "notebook_params": {...}, "job_parameters": {"env": "prod"}} # API rejects

I also checked whether an escape hatch already existed: job_parameters={} does not work, because not json.get("job_parameters") treats an empty dict as falsy and injects params anyway. So the new flag is genuinely necessary — the approach is right.

Verification I ran:

  • Reverted the guard in _build_run_now_payload → the new test fails. Restored → full operator suite passes (201 tests).
  • prek run --stage pre-commit clean on the diff.

The direction is good. I left three inline notes — the first one is the substantive one (default behaviour still leaves existing users broken); the others are the docstring and test coverage.

One more docs point I could not anchor inline, because the file is not part of this diff: providers/databricks/docs/operators/run_now.rst (the "Forwarding Airflow Dag params as Databricks job parameters" section, around line 60) still documents forwarding as unconditional. That guide is where users land when they hit this failure, so the opt-out should be discoverable there too — a sentence naming forward_dag_params=False, plus the mutual-exclusivity constraint with the legacy param slots.

Non-blocking, out of scope for this PR: #66613 added the same forwarding to DatabricksCreateJobsOperator (parameters) and DatabricksSubmitRunOperator (per-task dict slots), which have no opt-out. Scoping this to RunNow matches the issue, so no change needed here — just flagging it in case the flag should be applied consistently in a follow-up.


Drafted-by: Claude Code (Opus 5)

… parameter slots are used
The Databricks API run-now endpoint rejects job_parameters when combined with notebook_params, python_params, jar_params, spark_submit_params, python_named_params, or dbt_commands. This update automatically skips forwarding DAG-level params into job_parameters if any of those conflicting slots are present in the payload. Also updates docstrings, operator RST documentation, and unit tests.
@onlyarnav
onlyarnavforce-pushed the fix-databricks-run-now-forward-params branch from fa593d3 to 90e726bCompareJuly 27, 2026 13:15

@moomindanimoomindani left a comment

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.

All three addressed, verified by running 90e726b6 rather than reading the summary. The auto-skip is implemented as suggested, and the four paths behave correctly:

Dag params + notebook_params -> {job_id, notebook_params} # regression repaired, no user change
explicit job_parameters + slot -> both preserved # user intent respected
Dag params, no slot -> {job_id, job_parameters} # forwarding still works
forward_dag_params=False -> {job_id} # flag still honoured

Keeping an explicitly-passed job_parameters rather than silently dropping it is the right call — only the implicit forwarding is skipped, so a user who deliberately combined them still gets the API error instead of a silent behaviour change. 207 tests pass, and the test_execute_does_not_mutate_json_template_field edit is a necessary consequence of the skip logic with its assertions intact.

I went back to the workspace to check the approach itself, and found the constraint is bidirectional — worth knowing, though it does not change my assessment:

Job configSentResult
has job-level parametersnotebook_params onlyrejected: "Cannot use legacy parameters (...) because the job has job parameters configured"
has job-level parametersjob_parameters onlyaccepted
no job-level parametersnotebook_params onlyaccepted
eitherbothrejected: "job_parameters can not be used in combination with notebook_params"

So for a job that does declare job-level parameters, skipping the injection trades one rejection for the other. But that combination was already impossible before #66613, so the set of broken Dags is unchanged — and the case your fix actually repairs (job without job-level parameters + legacy slot + Dag params) is a genuine #66613 regression. The skip condition maps correctly onto the API constraint, and forward_dag_params still earns its place for jobs whose entry point rejects extra params even with no slot conflict. Approach looks right to me.

One optional docs nit, non-blocking: the new note says job_parameters cannot be combined with the legacy slots, which is accurate but narrower than the API's actual rule. A reader may conclude "then I'll just use notebook_params" — which also fails if the job declares job-level parameters. A clause like "and the legacy slots cannot be used at all against a job that declares job-level parameters" would close that gap. Fine to leave for a follow-up.


Drafted-by: Claude Code (Opus 5)

@potiukpotiuk added the ready for maintainer review Set after triaging when all criteria pass. label Jul 28, 2026
@eladkal
eladkal merged commit 52133f1 into apache:mainAug 6, 2026
83 checks passed
dabla pushed a commit to dabla/airflow that referenced this pull request Aug 14, 2026
…owOperator (apache#70130)
* Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator
The DatabricksRunNowOperator always forwards Dag-level parameters as job_parameters, but some Databricks jobs do not expect or accept these parameters, causing task failures. This change introduces a forward_dag_params boolean parameter (defaulting to True) to allow opting out. Additionally, this fixes a Windows-specific encoding issue when parsing imports in static checks, guards the os.register_at_fork calls to prevent startup crashes on Windows, and adds a fcntl mock inside conftest to enable the local test suite on Windows.
* Skip Databricks job_parameters auto-injection when conflicting legacy parameter slots are used
The Databricks API run-now endpoint rejects job_parameters when combined with notebook_params, python_params, jar_params, spark_submit_params, python_named_params, or dbt_commands. This update automatically skips forwarding DAG-level params into job_parameters if any of those conflicting slots are present in the payload. Also updates docstrings, operator RST documentation, and unit tests.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersprovider:databricksready for maintainer reviewSet after triaging when all criteria pass.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DatabricksRunNowOperator always pass parameters to Databricks Job

6 participants

@onlyarnav@eladkal@moomindani@amoghrajesh@jroachgolf84@potiuk
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Providers: Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator - #70130

Merged
eladkal merged 3 commits into
apache:mainfrom
onlyarnav:fix-databricks-run-now-forward-params
Aug 6, 2026
Merged

Providers: Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator#70130
eladkal merged 3 commits into
apache:mainfrom
onlyarnav:fix-databricks-run-now-forward-params

Conversation

@onlyarnav

Copy link
Copy Markdown
Member

Description

This PR introduces an option to opt out of forwarding Dag-level parameters in the DatabricksRunNowOperator.

In PR #66613 (for issue #39002), parameter forwarding was introduced such that the operator's params dict is automatically forwarded as job_parameters when no job_parameters are specified. However, this changes the payload for Databricks jobs and breaks execution for jobs whose entry points do not expect or accept additional parameters.

To resolve this compatibility issue, this PR:

  1. Adds a new boolean parameter forward_dag_params (default: True) to DatabricksRunNowOperator.
  2. Checks self.forward_dag_params when constructing the payload inside _build_run_now_payload before merging self.params.
  3. Adds unit tests to verify that Dag-level parameters are not forwarded when forward_dag_params=False.
  4. Fixes minor Windows-specific issues (e.g. file encoding, os.register_at_fork, and a mock fcntl) to enable executing the local test suite on Windows development hosts.

closes: #70121


Was generative AI tooling used to co-author this PR?
  • Yes (Google Antigravity)

Generated-by: Google Antigravity following the guidelines

@jroachgolf84jroachgolf84 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please review my comments, specifically, there are a few changes in there I don't think should be in there.

Comment threadproviders/databricks/tests/conftest.py
Comment threadscripts/ci/prek/common_prek_utils.py
amoghrajesh
amoghrajesh previously requested changes Jul 20, 2026

@amoghrajeshamoghrajesh left a comment

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.

@onlyarnav there is some unrelated changes in your PR diff, please revise it and keep the changes only scoped to this PR.

Comment threadproviders/databricks/tests/conftest.py Outdated
Comment threadshared/observability/src/airflow_shared/observability/metrics/stats.py Outdated
…owOperator
The DatabricksRunNowOperator always forwards Dag-level parameters as job_parameters, but some Databricks jobs do not expect or accept these parameters, causing task failures. This change introduces a forward_dag_params boolean parameter (defaulting to True) to allow opting out. Additionally, this fixes a Windows-specific encoding issue when parsing imports in static checks, guards the os.register_at_fork calls to prevent startup crashes on Windows, and adds a fcntl mock inside conftest to enable the local test suite on Windows.
@onlyarnav
onlyarnavforce-pushed the fix-databricks-run-now-forward-params branch from 6d0b519 to 340211aCompareJuly 20, 2026 14:49

@jroachgolf84jroachgolf84 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the changes, LGTM.

@eladkal

Copy link
Copy Markdown
Contributor

cc @moomindani for a review from Databricks team

@moomindanimoomindani left a comment

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.

Thanks for the fix, and thanks for cleaning up the unrelated Windows changes — the diff is nicely scoped now.

I validated this against a real Databricks workspace, and the regression is more severe than the issue describes. The run-now endpoint rejects job_parameters outright when combined with any of the legacy param slots. All six confirmed:

job_parameters can not be used in combination with notebook_params
job_parameters can not be used in combination with python_params
job_parameters can not be used in combination with jar_params
job_parameters can not be used in combination with spark_submit_params
job_parameters can not be used in combination with python_named_params
job_parameters can not be used in combination with dbt_commands

Since Dag-level params propagate to the operator implicitly, a Dag like this has been failing since 7.16.0 with no user action:

withDAG("d", params={"env": "prod"}):
DatabricksRunNowOperator(task_id="t", job_id=1, notebook_params={"foo": "bar"})
# payload -> {"job_id": 1, "notebook_params": {...}, "job_parameters": {"env": "prod"}} # API rejects

I also checked whether an escape hatch already existed: job_parameters={} does not work, because not json.get("job_parameters") treats an empty dict as falsy and injects params anyway. So the new flag is genuinely necessary — the approach is right.

Verification I ran:

  • Reverted the guard in _build_run_now_payload → the new test fails. Restored → full operator suite passes (201 tests).
  • prek run --stage pre-commit clean on the diff.

The direction is good. I left three inline notes — the first one is the substantive one (default behaviour still leaves existing users broken); the others are the docstring and test coverage.

One more docs point I could not anchor inline, because the file is not part of this diff: providers/databricks/docs/operators/run_now.rst (the "Forwarding Airflow Dag params as Databricks job parameters" section, around line 60) still documents forwarding as unconditional. That guide is where users land when they hit this failure, so the opt-out should be discoverable there too — a sentence naming forward_dag_params=False, plus the mutual-exclusivity constraint with the legacy param slots.

Non-blocking, out of scope for this PR: #66613 added the same forwarding to DatabricksCreateJobsOperator (parameters) and DatabricksSubmitRunOperator (per-task dict slots), which have no opt-out. Scoping this to RunNow matches the issue, so no change needed here — just flagging it in case the flag should be applied consistently in a follow-up.


Drafted-by: Claude Code (Opus 5)

… parameter slots are used
The Databricks API run-now endpoint rejects job_parameters when combined with notebook_params, python_params, jar_params, spark_submit_params, python_named_params, or dbt_commands. This update automatically skips forwarding DAG-level params into job_parameters if any of those conflicting slots are present in the payload. Also updates docstrings, operator RST documentation, and unit tests.
@onlyarnav
onlyarnavforce-pushed the fix-databricks-run-now-forward-params branch from fa593d3 to 90e726bCompareJuly 27, 2026 13:15

@moomindanimoomindani left a comment

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.

All three addressed, verified by running 90e726b6 rather than reading the summary. The auto-skip is implemented as suggested, and the four paths behave correctly:

Dag params + notebook_params -> {job_id, notebook_params} # regression repaired, no user change
explicit job_parameters + slot -> both preserved # user intent respected
Dag params, no slot -> {job_id, job_parameters} # forwarding still works
forward_dag_params=False -> {job_id} # flag still honoured

Keeping an explicitly-passed job_parameters rather than silently dropping it is the right call — only the implicit forwarding is skipped, so a user who deliberately combined them still gets the API error instead of a silent behaviour change. 207 tests pass, and the test_execute_does_not_mutate_json_template_field edit is a necessary consequence of the skip logic with its assertions intact.

I went back to the workspace to check the approach itself, and found the constraint is bidirectional — worth knowing, though it does not change my assessment:

Job configSentResult
has job-level parametersnotebook_params onlyrejected: "Cannot use legacy parameters (...) because the job has job parameters configured"
has job-level parametersjob_parameters onlyaccepted
no job-level parametersnotebook_params onlyaccepted
eitherbothrejected: "job_parameters can not be used in combination with notebook_params"

So for a job that does declare job-level parameters, skipping the injection trades one rejection for the other. But that combination was already impossible before #66613, so the set of broken Dags is unchanged — and the case your fix actually repairs (job without job-level parameters + legacy slot + Dag params) is a genuine #66613 regression. The skip condition maps correctly onto the API constraint, and forward_dag_params still earns its place for jobs whose entry point rejects extra params even with no slot conflict. Approach looks right to me.

One optional docs nit, non-blocking: the new note says job_parameters cannot be combined with the legacy slots, which is accurate but narrower than the API's actual rule. A reader may conclude "then I'll just use notebook_params" — which also fails if the job declares job-level parameters. A clause like "and the legacy slots cannot be used at all against a job that declares job-level parameters" would close that gap. Fine to leave for a follow-up.


Drafted-by: Claude Code (Opus 5)

@potiukpotiuk added the ready for maintainer review Set after triaging when all criteria pass. label Jul 28, 2026
@eladkal
eladkal merged commit 52133f1 into apache:mainAug 6, 2026
83 checks passed
dabla pushed a commit to dabla/airflow that referenced this pull request Aug 14, 2026
…owOperator (apache#70130)
* Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator
The DatabricksRunNowOperator always forwards Dag-level parameters as job_parameters, but some Databricks jobs do not expect or accept these parameters, causing task failures. This change introduces a forward_dag_params boolean parameter (defaulting to True) to allow opting out. Additionally, this fixes a Windows-specific encoding issue when parsing imports in static checks, guards the os.register_at_fork calls to prevent startup crashes on Windows, and adds a fcntl mock inside conftest to enable the local test suite on Windows.
* Skip Databricks job_parameters auto-injection when conflicting legacy parameter slots are used
The Databricks API run-now endpoint rejects job_parameters when combined with notebook_params, python_params, jar_params, spark_submit_params, python_named_params, or dbt_commands. This update automatically skips forwarding DAG-level params into job_parameters if any of those conflicting slots are present in the payload. Also updates docstrings, operator RST documentation, and unit tests.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersprovider:databricksready for maintainer reviewSet after triaging when all criteria pass.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DatabricksRunNowOperator always pass parameters to Databricks Job

6 participants

@onlyarnav@eladkal@moomindani@amoghrajesh@jroachgolf84@potiuk
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Providers: Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator - #70130

Merged
eladkal merged 3 commits into
apache:mainfrom
onlyarnav:fix-databricks-run-now-forward-params
Aug 6, 2026
Merged

Providers: Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator#70130
eladkal merged 3 commits into
apache:mainfrom
onlyarnav:fix-databricks-run-now-forward-params

Conversation

@onlyarnav

Copy link
Copy Markdown
Member

Description

This PR introduces an option to opt out of forwarding Dag-level parameters in the DatabricksRunNowOperator.

In PR #66613 (for issue #39002), parameter forwarding was introduced such that the operator's params dict is automatically forwarded as job_parameters when no job_parameters are specified. However, this changes the payload for Databricks jobs and breaks execution for jobs whose entry points do not expect or accept additional parameters.

To resolve this compatibility issue, this PR:

  1. Adds a new boolean parameter forward_dag_params (default: True) to DatabricksRunNowOperator.
  2. Checks self.forward_dag_params when constructing the payload inside _build_run_now_payload before merging self.params.
  3. Adds unit tests to verify that Dag-level parameters are not forwarded when forward_dag_params=False.
  4. Fixes minor Windows-specific issues (e.g. file encoding, os.register_at_fork, and a mock fcntl) to enable executing the local test suite on Windows development hosts.

closes: #70121


Was generative AI tooling used to co-author this PR?
  • Yes (Google Antigravity)

Generated-by: Google Antigravity following the guidelines

@jroachgolf84jroachgolf84 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please review my comments, specifically, there are a few changes in there I don't think should be in there.

Comment threadproviders/databricks/tests/conftest.py
Comment threadscripts/ci/prek/common_prek_utils.py
amoghrajesh
amoghrajesh previously requested changes Jul 20, 2026

@amoghrajeshamoghrajesh left a comment

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.

@onlyarnav there is some unrelated changes in your PR diff, please revise it and keep the changes only scoped to this PR.

Comment threadproviders/databricks/tests/conftest.py Outdated
Comment threadshared/observability/src/airflow_shared/observability/metrics/stats.py Outdated
…owOperator
The DatabricksRunNowOperator always forwards Dag-level parameters as job_parameters, but some Databricks jobs do not expect or accept these parameters, causing task failures. This change introduces a forward_dag_params boolean parameter (defaulting to True) to allow opting out. Additionally, this fixes a Windows-specific encoding issue when parsing imports in static checks, guards the os.register_at_fork calls to prevent startup crashes on Windows, and adds a fcntl mock inside conftest to enable the local test suite on Windows.
@onlyarnav
onlyarnavforce-pushed the fix-databricks-run-now-forward-params branch from 6d0b519 to 340211aCompareJuly 20, 2026 14:49

@jroachgolf84jroachgolf84 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the changes, LGTM.

@eladkal

Copy link
Copy Markdown
Contributor

cc @moomindani for a review from Databricks team

@moomindanimoomindani left a comment

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.

Thanks for the fix, and thanks for cleaning up the unrelated Windows changes — the diff is nicely scoped now.

I validated this against a real Databricks workspace, and the regression is more severe than the issue describes. The run-now endpoint rejects job_parameters outright when combined with any of the legacy param slots. All six confirmed:

job_parameters can not be used in combination with notebook_params
job_parameters can not be used in combination with python_params
job_parameters can not be used in combination with jar_params
job_parameters can not be used in combination with spark_submit_params
job_parameters can not be used in combination with python_named_params
job_parameters can not be used in combination with dbt_commands

Since Dag-level params propagate to the operator implicitly, a Dag like this has been failing since 7.16.0 with no user action:

withDAG("d", params={"env": "prod"}):
DatabricksRunNowOperator(task_id="t", job_id=1, notebook_params={"foo": "bar"})
# payload -> {"job_id": 1, "notebook_params": {...}, "job_parameters": {"env": "prod"}} # API rejects

I also checked whether an escape hatch already existed: job_parameters={} does not work, because not json.get("job_parameters") treats an empty dict as falsy and injects params anyway. So the new flag is genuinely necessary — the approach is right.

Verification I ran:

  • Reverted the guard in _build_run_now_payload → the new test fails. Restored → full operator suite passes (201 tests).
  • prek run --stage pre-commit clean on the diff.

The direction is good. I left three inline notes — the first one is the substantive one (default behaviour still leaves existing users broken); the others are the docstring and test coverage.

One more docs point I could not anchor inline, because the file is not part of this diff: providers/databricks/docs/operators/run_now.rst (the "Forwarding Airflow Dag params as Databricks job parameters" section, around line 60) still documents forwarding as unconditional. That guide is where users land when they hit this failure, so the opt-out should be discoverable there too — a sentence naming forward_dag_params=False, plus the mutual-exclusivity constraint with the legacy param slots.

Non-blocking, out of scope for this PR: #66613 added the same forwarding to DatabricksCreateJobsOperator (parameters) and DatabricksSubmitRunOperator (per-task dict slots), which have no opt-out. Scoping this to RunNow matches the issue, so no change needed here — just flagging it in case the flag should be applied consistently in a follow-up.


Drafted-by: Claude Code (Opus 5)

… parameter slots are used
The Databricks API run-now endpoint rejects job_parameters when combined with notebook_params, python_params, jar_params, spark_submit_params, python_named_params, or dbt_commands. This update automatically skips forwarding DAG-level params into job_parameters if any of those conflicting slots are present in the payload. Also updates docstrings, operator RST documentation, and unit tests.
@onlyarnav
onlyarnavforce-pushed the fix-databricks-run-now-forward-params branch from fa593d3 to 90e726bCompareJuly 27, 2026 13:15

@moomindanimoomindani left a comment

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.

All three addressed, verified by running 90e726b6 rather than reading the summary. The auto-skip is implemented as suggested, and the four paths behave correctly:

Dag params + notebook_params -> {job_id, notebook_params} # regression repaired, no user change
explicit job_parameters + slot -> both preserved # user intent respected
Dag params, no slot -> {job_id, job_parameters} # forwarding still works
forward_dag_params=False -> {job_id} # flag still honoured

Keeping an explicitly-passed job_parameters rather than silently dropping it is the right call — only the implicit forwarding is skipped, so a user who deliberately combined them still gets the API error instead of a silent behaviour change. 207 tests pass, and the test_execute_does_not_mutate_json_template_field edit is a necessary consequence of the skip logic with its assertions intact.

I went back to the workspace to check the approach itself, and found the constraint is bidirectional — worth knowing, though it does not change my assessment:

Job configSentResult
has job-level parametersnotebook_params onlyrejected: "Cannot use legacy parameters (...) because the job has job parameters configured"
has job-level parametersjob_parameters onlyaccepted
no job-level parametersnotebook_params onlyaccepted
eitherbothrejected: "job_parameters can not be used in combination with notebook_params"

So for a job that does declare job-level parameters, skipping the injection trades one rejection for the other. But that combination was already impossible before #66613, so the set of broken Dags is unchanged — and the case your fix actually repairs (job without job-level parameters + legacy slot + Dag params) is a genuine #66613 regression. The skip condition maps correctly onto the API constraint, and forward_dag_params still earns its place for jobs whose entry point rejects extra params even with no slot conflict. Approach looks right to me.

One optional docs nit, non-blocking: the new note says job_parameters cannot be combined with the legacy slots, which is accurate but narrower than the API's actual rule. A reader may conclude "then I'll just use notebook_params" — which also fails if the job declares job-level parameters. A clause like "and the legacy slots cannot be used at all against a job that declares job-level parameters" would close that gap. Fine to leave for a follow-up.


Drafted-by: Claude Code (Opus 5)

@potiukpotiuk added the ready for maintainer review Set after triaging when all criteria pass. label Jul 28, 2026
@eladkal
eladkal merged commit 52133f1 into apache:mainAug 6, 2026
83 checks passed
dabla pushed a commit to dabla/airflow that referenced this pull request Aug 14, 2026
…owOperator (apache#70130)
* Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator
The DatabricksRunNowOperator always forwards Dag-level parameters as job_parameters, but some Databricks jobs do not expect or accept these parameters, causing task failures. This change introduces a forward_dag_params boolean parameter (defaulting to True) to allow opting out. Additionally, this fixes a Windows-specific encoding issue when parsing imports in static checks, guards the os.register_at_fork calls to prevent startup crashes on Windows, and adds a fcntl mock inside conftest to enable the local test suite on Windows.
* Skip Databricks job_parameters auto-injection when conflicting legacy parameter slots are used
The Databricks API run-now endpoint rejects job_parameters when combined with notebook_params, python_params, jar_params, spark_submit_params, python_named_params, or dbt_commands. This update automatically skips forwarding DAG-level params into job_parameters if any of those conflicting slots are present in the payload. Also updates docstrings, operator RST documentation, and unit tests.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersprovider:databricksready for maintainer reviewSet after triaging when all criteria pass.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DatabricksRunNowOperator always pass parameters to Databricks Job

6 participants

@onlyarnav@eladkal@moomindani@amoghrajesh@jroachgolf84@potiuk
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Providers: Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator - #70130

Merged
eladkal merged 3 commits into
apache:mainfrom
onlyarnav:fix-databricks-run-now-forward-params
Aug 6, 2026
Merged

Providers: Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator#70130
eladkal merged 3 commits into
apache:mainfrom
onlyarnav:fix-databricks-run-now-forward-params

Conversation

@onlyarnav

Copy link
Copy Markdown
Member

Description

This PR introduces an option to opt out of forwarding Dag-level parameters in the DatabricksRunNowOperator.

In PR #66613 (for issue #39002), parameter forwarding was introduced such that the operator's params dict is automatically forwarded as job_parameters when no job_parameters are specified. However, this changes the payload for Databricks jobs and breaks execution for jobs whose entry points do not expect or accept additional parameters.

To resolve this compatibility issue, this PR:

  1. Adds a new boolean parameter forward_dag_params (default: True) to DatabricksRunNowOperator.
  2. Checks self.forward_dag_params when constructing the payload inside _build_run_now_payload before merging self.params.
  3. Adds unit tests to verify that Dag-level parameters are not forwarded when forward_dag_params=False.
  4. Fixes minor Windows-specific issues (e.g. file encoding, os.register_at_fork, and a mock fcntl) to enable executing the local test suite on Windows development hosts.

closes: #70121


Was generative AI tooling used to co-author this PR?
  • Yes (Google Antigravity)

Generated-by: Google Antigravity following the guidelines

@jroachgolf84jroachgolf84 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please review my comments, specifically, there are a few changes in there I don't think should be in there.

Comment threadproviders/databricks/tests/conftest.py
Comment threadscripts/ci/prek/common_prek_utils.py
amoghrajesh
amoghrajesh previously requested changes Jul 20, 2026

@amoghrajeshamoghrajesh left a comment

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.

@onlyarnav there is some unrelated changes in your PR diff, please revise it and keep the changes only scoped to this PR.

Comment threadproviders/databricks/tests/conftest.py Outdated
Comment threadshared/observability/src/airflow_shared/observability/metrics/stats.py Outdated
…owOperator
The DatabricksRunNowOperator always forwards Dag-level parameters as job_parameters, but some Databricks jobs do not expect or accept these parameters, causing task failures. This change introduces a forward_dag_params boolean parameter (defaulting to True) to allow opting out. Additionally, this fixes a Windows-specific encoding issue when parsing imports in static checks, guards the os.register_at_fork calls to prevent startup crashes on Windows, and adds a fcntl mock inside conftest to enable the local test suite on Windows.
@onlyarnav
onlyarnavforce-pushed the fix-databricks-run-now-forward-params branch from 6d0b519 to 340211aCompareJuly 20, 2026 14:49

@jroachgolf84jroachgolf84 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the changes, LGTM.

@eladkal

Copy link
Copy Markdown
Contributor

cc @moomindani for a review from Databricks team

@moomindanimoomindani left a comment

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.

Thanks for the fix, and thanks for cleaning up the unrelated Windows changes — the diff is nicely scoped now.

I validated this against a real Databricks workspace, and the regression is more severe than the issue describes. The run-now endpoint rejects job_parameters outright when combined with any of the legacy param slots. All six confirmed:

job_parameters can not be used in combination with notebook_params
job_parameters can not be used in combination with python_params
job_parameters can not be used in combination with jar_params
job_parameters can not be used in combination with spark_submit_params
job_parameters can not be used in combination with python_named_params
job_parameters can not be used in combination with dbt_commands

Since Dag-level params propagate to the operator implicitly, a Dag like this has been failing since 7.16.0 with no user action:

withDAG("d", params={"env": "prod"}):
DatabricksRunNowOperator(task_id="t", job_id=1, notebook_params={"foo": "bar"})
# payload -> {"job_id": 1, "notebook_params": {...}, "job_parameters": {"env": "prod"}} # API rejects

I also checked whether an escape hatch already existed: job_parameters={} does not work, because not json.get("job_parameters") treats an empty dict as falsy and injects params anyway. So the new flag is genuinely necessary — the approach is right.

Verification I ran:

  • Reverted the guard in _build_run_now_payload → the new test fails. Restored → full operator suite passes (201 tests).
  • prek run --stage pre-commit clean on the diff.

The direction is good. I left three inline notes — the first one is the substantive one (default behaviour still leaves existing users broken); the others are the docstring and test coverage.

One more docs point I could not anchor inline, because the file is not part of this diff: providers/databricks/docs/operators/run_now.rst (the "Forwarding Airflow Dag params as Databricks job parameters" section, around line 60) still documents forwarding as unconditional. That guide is where users land when they hit this failure, so the opt-out should be discoverable there too — a sentence naming forward_dag_params=False, plus the mutual-exclusivity constraint with the legacy param slots.

Non-blocking, out of scope for this PR: #66613 added the same forwarding to DatabricksCreateJobsOperator (parameters) and DatabricksSubmitRunOperator (per-task dict slots), which have no opt-out. Scoping this to RunNow matches the issue, so no change needed here — just flagging it in case the flag should be applied consistently in a follow-up.


Drafted-by: Claude Code (Opus 5)

… parameter slots are used
The Databricks API run-now endpoint rejects job_parameters when combined with notebook_params, python_params, jar_params, spark_submit_params, python_named_params, or dbt_commands. This update automatically skips forwarding DAG-level params into job_parameters if any of those conflicting slots are present in the payload. Also updates docstrings, operator RST documentation, and unit tests.
@onlyarnav
onlyarnavforce-pushed the fix-databricks-run-now-forward-params branch from fa593d3 to 90e726bCompareJuly 27, 2026 13:15

@moomindanimoomindani left a comment

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.

All three addressed, verified by running 90e726b6 rather than reading the summary. The auto-skip is implemented as suggested, and the four paths behave correctly:

Dag params + notebook_params -> {job_id, notebook_params} # regression repaired, no user change
explicit job_parameters + slot -> both preserved # user intent respected
Dag params, no slot -> {job_id, job_parameters} # forwarding still works
forward_dag_params=False -> {job_id} # flag still honoured

Keeping an explicitly-passed job_parameters rather than silently dropping it is the right call — only the implicit forwarding is skipped, so a user who deliberately combined them still gets the API error instead of a silent behaviour change. 207 tests pass, and the test_execute_does_not_mutate_json_template_field edit is a necessary consequence of the skip logic with its assertions intact.

I went back to the workspace to check the approach itself, and found the constraint is bidirectional — worth knowing, though it does not change my assessment:

Job configSentResult
has job-level parametersnotebook_params onlyrejected: "Cannot use legacy parameters (...) because the job has job parameters configured"
has job-level parametersjob_parameters onlyaccepted
no job-level parametersnotebook_params onlyaccepted
eitherbothrejected: "job_parameters can not be used in combination with notebook_params"

So for a job that does declare job-level parameters, skipping the injection trades one rejection for the other. But that combination was already impossible before #66613, so the set of broken Dags is unchanged — and the case your fix actually repairs (job without job-level parameters + legacy slot + Dag params) is a genuine #66613 regression. The skip condition maps correctly onto the API constraint, and forward_dag_params still earns its place for jobs whose entry point rejects extra params even with no slot conflict. Approach looks right to me.

One optional docs nit, non-blocking: the new note says job_parameters cannot be combined with the legacy slots, which is accurate but narrower than the API's actual rule. A reader may conclude "then I'll just use notebook_params" — which also fails if the job declares job-level parameters. A clause like "and the legacy slots cannot be used at all against a job that declares job-level parameters" would close that gap. Fine to leave for a follow-up.


Drafted-by: Claude Code (Opus 5)

@potiukpotiuk added the ready for maintainer review Set after triaging when all criteria pass. label Jul 28, 2026
@eladkal
eladkal merged commit 52133f1 into apache:mainAug 6, 2026
83 checks passed
dabla pushed a commit to dabla/airflow that referenced this pull request Aug 14, 2026
…owOperator (apache#70130)
* Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator
The DatabricksRunNowOperator always forwards Dag-level parameters as job_parameters, but some Databricks jobs do not expect or accept these parameters, causing task failures. This change introduces a forward_dag_params boolean parameter (defaulting to True) to allow opting out. Additionally, this fixes a Windows-specific encoding issue when parsing imports in static checks, guards the os.register_at_fork calls to prevent startup crashes on Windows, and adds a fcntl mock inside conftest to enable the local test suite on Windows.
* Skip Databricks job_parameters auto-injection when conflicting legacy parameter slots are used
The Databricks API run-now endpoint rejects job_parameters when combined with notebook_params, python_params, jar_params, spark_submit_params, python_named_params, or dbt_commands. This update automatically skips forwarding DAG-level params into job_parameters if any of those conflicting slots are present in the payload. Also updates docstrings, operator RST documentation, and unit tests.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersprovider:databricksready for maintainer reviewSet after triaging when all criteria pass.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DatabricksRunNowOperator always pass parameters to Databricks Job

6 participants

@onlyarnav@eladkal@moomindani@amoghrajesh@jroachgolf84@potiuk
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Providers: Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator - #70130

Merged
eladkal merged 3 commits into
apache:mainfrom
onlyarnav:fix-databricks-run-now-forward-params
Aug 6, 2026
Merged

Providers: Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator#70130
eladkal merged 3 commits into
apache:mainfrom
onlyarnav:fix-databricks-run-now-forward-params

Conversation

@onlyarnav

Copy link
Copy Markdown
Member

Description

This PR introduces an option to opt out of forwarding Dag-level parameters in the DatabricksRunNowOperator.

In PR #66613 (for issue #39002), parameter forwarding was introduced such that the operator's params dict is automatically forwarded as job_parameters when no job_parameters are specified. However, this changes the payload for Databricks jobs and breaks execution for jobs whose entry points do not expect or accept additional parameters.

To resolve this compatibility issue, this PR:

  1. Adds a new boolean parameter forward_dag_params (default: True) to DatabricksRunNowOperator.
  2. Checks self.forward_dag_params when constructing the payload inside _build_run_now_payload before merging self.params.
  3. Adds unit tests to verify that Dag-level parameters are not forwarded when forward_dag_params=False.
  4. Fixes minor Windows-specific issues (e.g. file encoding, os.register_at_fork, and a mock fcntl) to enable executing the local test suite on Windows development hosts.

closes: #70121


Was generative AI tooling used to co-author this PR?
  • Yes (Google Antigravity)

Generated-by: Google Antigravity following the guidelines

@jroachgolf84jroachgolf84 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please review my comments, specifically, there are a few changes in there I don't think should be in there.

Comment threadproviders/databricks/tests/conftest.py
Comment threadscripts/ci/prek/common_prek_utils.py
amoghrajesh
amoghrajesh previously requested changes Jul 20, 2026

@amoghrajeshamoghrajesh left a comment

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.

@onlyarnav there is some unrelated changes in your PR diff, please revise it and keep the changes only scoped to this PR.

Comment threadproviders/databricks/tests/conftest.py Outdated
Comment threadshared/observability/src/airflow_shared/observability/metrics/stats.py Outdated
…owOperator
The DatabricksRunNowOperator always forwards Dag-level parameters as job_parameters, but some Databricks jobs do not expect or accept these parameters, causing task failures. This change introduces a forward_dag_params boolean parameter (defaulting to True) to allow opting out. Additionally, this fixes a Windows-specific encoding issue when parsing imports in static checks, guards the os.register_at_fork calls to prevent startup crashes on Windows, and adds a fcntl mock inside conftest to enable the local test suite on Windows.
@onlyarnav
onlyarnavforce-pushed the fix-databricks-run-now-forward-params branch from 6d0b519 to 340211aCompareJuly 20, 2026 14:49

@jroachgolf84jroachgolf84 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the changes, LGTM.

@eladkal

Copy link
Copy Markdown
Contributor

cc @moomindani for a review from Databricks team

@moomindanimoomindani left a comment

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.

Thanks for the fix, and thanks for cleaning up the unrelated Windows changes — the diff is nicely scoped now.

I validated this against a real Databricks workspace, and the regression is more severe than the issue describes. The run-now endpoint rejects job_parameters outright when combined with any of the legacy param slots. All six confirmed:

job_parameters can not be used in combination with notebook_params
job_parameters can not be used in combination with python_params
job_parameters can not be used in combination with jar_params
job_parameters can not be used in combination with spark_submit_params
job_parameters can not be used in combination with python_named_params
job_parameters can not be used in combination with dbt_commands

Since Dag-level params propagate to the operator implicitly, a Dag like this has been failing since 7.16.0 with no user action:

withDAG("d", params={"env": "prod"}):
DatabricksRunNowOperator(task_id="t", job_id=1, notebook_params={"foo": "bar"})
# payload -> {"job_id": 1, "notebook_params": {...}, "job_parameters": {"env": "prod"}} # API rejects

I also checked whether an escape hatch already existed: job_parameters={} does not work, because not json.get("job_parameters") treats an empty dict as falsy and injects params anyway. So the new flag is genuinely necessary — the approach is right.

Verification I ran:

  • Reverted the guard in _build_run_now_payload → the new test fails. Restored → full operator suite passes (201 tests).
  • prek run --stage pre-commit clean on the diff.

The direction is good. I left three inline notes — the first one is the substantive one (default behaviour still leaves existing users broken); the others are the docstring and test coverage.

One more docs point I could not anchor inline, because the file is not part of this diff: providers/databricks/docs/operators/run_now.rst (the "Forwarding Airflow Dag params as Databricks job parameters" section, around line 60) still documents forwarding as unconditional. That guide is where users land when they hit this failure, so the opt-out should be discoverable there too — a sentence naming forward_dag_params=False, plus the mutual-exclusivity constraint with the legacy param slots.

Non-blocking, out of scope for this PR: #66613 added the same forwarding to DatabricksCreateJobsOperator (parameters) and DatabricksSubmitRunOperator (per-task dict slots), which have no opt-out. Scoping this to RunNow matches the issue, so no change needed here — just flagging it in case the flag should be applied consistently in a follow-up.


Drafted-by: Claude Code (Opus 5)

… parameter slots are used
The Databricks API run-now endpoint rejects job_parameters when combined with notebook_params, python_params, jar_params, spark_submit_params, python_named_params, or dbt_commands. This update automatically skips forwarding DAG-level params into job_parameters if any of those conflicting slots are present in the payload. Also updates docstrings, operator RST documentation, and unit tests.
@onlyarnav
onlyarnavforce-pushed the fix-databricks-run-now-forward-params branch from fa593d3 to 90e726bCompareJuly 27, 2026 13:15

@moomindanimoomindani left a comment

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.

All three addressed, verified by running 90e726b6 rather than reading the summary. The auto-skip is implemented as suggested, and the four paths behave correctly:

Dag params + notebook_params -> {job_id, notebook_params} # regression repaired, no user change
explicit job_parameters + slot -> both preserved # user intent respected
Dag params, no slot -> {job_id, job_parameters} # forwarding still works
forward_dag_params=False -> {job_id} # flag still honoured

Keeping an explicitly-passed job_parameters rather than silently dropping it is the right call — only the implicit forwarding is skipped, so a user who deliberately combined them still gets the API error instead of a silent behaviour change. 207 tests pass, and the test_execute_does_not_mutate_json_template_field edit is a necessary consequence of the skip logic with its assertions intact.

I went back to the workspace to check the approach itself, and found the constraint is bidirectional — worth knowing, though it does not change my assessment:

Job configSentResult
has job-level parametersnotebook_params onlyrejected: "Cannot use legacy parameters (...) because the job has job parameters configured"
has job-level parametersjob_parameters onlyaccepted
no job-level parametersnotebook_params onlyaccepted
eitherbothrejected: "job_parameters can not be used in combination with notebook_params"

So for a job that does declare job-level parameters, skipping the injection trades one rejection for the other. But that combination was already impossible before #66613, so the set of broken Dags is unchanged — and the case your fix actually repairs (job without job-level parameters + legacy slot + Dag params) is a genuine #66613 regression. The skip condition maps correctly onto the API constraint, and forward_dag_params still earns its place for jobs whose entry point rejects extra params even with no slot conflict. Approach looks right to me.

One optional docs nit, non-blocking: the new note says job_parameters cannot be combined with the legacy slots, which is accurate but narrower than the API's actual rule. A reader may conclude "then I'll just use notebook_params" — which also fails if the job declares job-level parameters. A clause like "and the legacy slots cannot be used at all against a job that declares job-level parameters" would close that gap. Fine to leave for a follow-up.


Drafted-by: Claude Code (Opus 5)

@potiukpotiuk added the ready for maintainer review Set after triaging when all criteria pass. label Jul 28, 2026
@eladkal
eladkal merged commit 52133f1 into apache:mainAug 6, 2026
83 checks passed
dabla pushed a commit to dabla/airflow that referenced this pull request Aug 14, 2026
…owOperator (apache#70130)
* Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator
The DatabricksRunNowOperator always forwards Dag-level parameters as job_parameters, but some Databricks jobs do not expect or accept these parameters, causing task failures. This change introduces a forward_dag_params boolean parameter (defaulting to True) to allow opting out. Additionally, this fixes a Windows-specific encoding issue when parsing imports in static checks, guards the os.register_at_fork calls to prevent startup crashes on Windows, and adds a fcntl mock inside conftest to enable the local test suite on Windows.
* Skip Databricks job_parameters auto-injection when conflicting legacy parameter slots are used
The Databricks API run-now endpoint rejects job_parameters when combined with notebook_params, python_params, jar_params, spark_submit_params, python_named_params, or dbt_commands. This update automatically skips forwarding DAG-level params into job_parameters if any of those conflicting slots are present in the payload. Also updates docstrings, operator RST documentation, and unit tests.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersprovider:databricksready for maintainer reviewSet after triaging when all criteria pass.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DatabricksRunNowOperator always pass parameters to Databricks Job

6 participants

@onlyarnav@eladkal@moomindani@amoghrajesh@jroachgolf84@potiuk
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Providers: Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator - #70130

Merged
eladkal merged 3 commits into
apache:mainfrom
onlyarnav:fix-databricks-run-now-forward-params
Aug 6, 2026
Merged

Providers: Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator#70130
eladkal merged 3 commits into
apache:mainfrom
onlyarnav:fix-databricks-run-now-forward-params

Conversation

@onlyarnav

Copy link
Copy Markdown
Member

Description

This PR introduces an option to opt out of forwarding Dag-level parameters in the DatabricksRunNowOperator.

In PR #66613 (for issue #39002), parameter forwarding was introduced such that the operator's params dict is automatically forwarded as job_parameters when no job_parameters are specified. However, this changes the payload for Databricks jobs and breaks execution for jobs whose entry points do not expect or accept additional parameters.

To resolve this compatibility issue, this PR:

  1. Adds a new boolean parameter forward_dag_params (default: True) to DatabricksRunNowOperator.
  2. Checks self.forward_dag_params when constructing the payload inside _build_run_now_payload before merging self.params.
  3. Adds unit tests to verify that Dag-level parameters are not forwarded when forward_dag_params=False.
  4. Fixes minor Windows-specific issues (e.g. file encoding, os.register_at_fork, and a mock fcntl) to enable executing the local test suite on Windows development hosts.

closes: #70121


Was generative AI tooling used to co-author this PR?
  • Yes (Google Antigravity)

Generated-by: Google Antigravity following the guidelines

@jroachgolf84jroachgolf84 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please review my comments, specifically, there are a few changes in there I don't think should be in there.

Comment threadproviders/databricks/tests/conftest.py
Comment threadscripts/ci/prek/common_prek_utils.py
amoghrajesh
amoghrajesh previously requested changes Jul 20, 2026

@amoghrajeshamoghrajesh left a comment

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.

@onlyarnav there is some unrelated changes in your PR diff, please revise it and keep the changes only scoped to this PR.

Comment threadproviders/databricks/tests/conftest.py Outdated
Comment threadshared/observability/src/airflow_shared/observability/metrics/stats.py Outdated
…owOperator
The DatabricksRunNowOperator always forwards Dag-level parameters as job_parameters, but some Databricks jobs do not expect or accept these parameters, causing task failures. This change introduces a forward_dag_params boolean parameter (defaulting to True) to allow opting out. Additionally, this fixes a Windows-specific encoding issue when parsing imports in static checks, guards the os.register_at_fork calls to prevent startup crashes on Windows, and adds a fcntl mock inside conftest to enable the local test suite on Windows.
@onlyarnav
onlyarnavforce-pushed the fix-databricks-run-now-forward-params branch from 6d0b519 to 340211aCompareJuly 20, 2026 14:49

@jroachgolf84jroachgolf84 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the changes, LGTM.

@eladkal

Copy link
Copy Markdown
Contributor

cc @moomindani for a review from Databricks team

@moomindanimoomindani left a comment

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.

Thanks for the fix, and thanks for cleaning up the unrelated Windows changes — the diff is nicely scoped now.

I validated this against a real Databricks workspace, and the regression is more severe than the issue describes. The run-now endpoint rejects job_parameters outright when combined with any of the legacy param slots. All six confirmed:

job_parameters can not be used in combination with notebook_params
job_parameters can not be used in combination with python_params
job_parameters can not be used in combination with jar_params
job_parameters can not be used in combination with spark_submit_params
job_parameters can not be used in combination with python_named_params
job_parameters can not be used in combination with dbt_commands

Since Dag-level params propagate to the operator implicitly, a Dag like this has been failing since 7.16.0 with no user action:

withDAG("d", params={"env": "prod"}):
DatabricksRunNowOperator(task_id="t", job_id=1, notebook_params={"foo": "bar"})
# payload -> {"job_id": 1, "notebook_params": {...}, "job_parameters": {"env": "prod"}} # API rejects

I also checked whether an escape hatch already existed: job_parameters={} does not work, because not json.get("job_parameters") treats an empty dict as falsy and injects params anyway. So the new flag is genuinely necessary — the approach is right.

Verification I ran:

  • Reverted the guard in _build_run_now_payload → the new test fails. Restored → full operator suite passes (201 tests).
  • prek run --stage pre-commit clean on the diff.

The direction is good. I left three inline notes — the first one is the substantive one (default behaviour still leaves existing users broken); the others are the docstring and test coverage.

One more docs point I could not anchor inline, because the file is not part of this diff: providers/databricks/docs/operators/run_now.rst (the "Forwarding Airflow Dag params as Databricks job parameters" section, around line 60) still documents forwarding as unconditional. That guide is where users land when they hit this failure, so the opt-out should be discoverable there too — a sentence naming forward_dag_params=False, plus the mutual-exclusivity constraint with the legacy param slots.

Non-blocking, out of scope for this PR: #66613 added the same forwarding to DatabricksCreateJobsOperator (parameters) and DatabricksSubmitRunOperator (per-task dict slots), which have no opt-out. Scoping this to RunNow matches the issue, so no change needed here — just flagging it in case the flag should be applied consistently in a follow-up.


Drafted-by: Claude Code (Opus 5)

… parameter slots are used
The Databricks API run-now endpoint rejects job_parameters when combined with notebook_params, python_params, jar_params, spark_submit_params, python_named_params, or dbt_commands. This update automatically skips forwarding DAG-level params into job_parameters if any of those conflicting slots are present in the payload. Also updates docstrings, operator RST documentation, and unit tests.
@onlyarnav
onlyarnavforce-pushed the fix-databricks-run-now-forward-params branch from fa593d3 to 90e726bCompareJuly 27, 2026 13:15

@moomindanimoomindani left a comment

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.

All three addressed, verified by running 90e726b6 rather than reading the summary. The auto-skip is implemented as suggested, and the four paths behave correctly:

Dag params + notebook_params -> {job_id, notebook_params} # regression repaired, no user change
explicit job_parameters + slot -> both preserved # user intent respected
Dag params, no slot -> {job_id, job_parameters} # forwarding still works
forward_dag_params=False -> {job_id} # flag still honoured

Keeping an explicitly-passed job_parameters rather than silently dropping it is the right call — only the implicit forwarding is skipped, so a user who deliberately combined them still gets the API error instead of a silent behaviour change. 207 tests pass, and the test_execute_does_not_mutate_json_template_field edit is a necessary consequence of the skip logic with its assertions intact.

I went back to the workspace to check the approach itself, and found the constraint is bidirectional — worth knowing, though it does not change my assessment:

Job configSentResult
has job-level parametersnotebook_params onlyrejected: "Cannot use legacy parameters (...) because the job has job parameters configured"
has job-level parametersjob_parameters onlyaccepted
no job-level parametersnotebook_params onlyaccepted
eitherbothrejected: "job_parameters can not be used in combination with notebook_params"

So for a job that does declare job-level parameters, skipping the injection trades one rejection for the other. But that combination was already impossible before #66613, so the set of broken Dags is unchanged — and the case your fix actually repairs (job without job-level parameters + legacy slot + Dag params) is a genuine #66613 regression. The skip condition maps correctly onto the API constraint, and forward_dag_params still earns its place for jobs whose entry point rejects extra params even with no slot conflict. Approach looks right to me.

One optional docs nit, non-blocking: the new note says job_parameters cannot be combined with the legacy slots, which is accurate but narrower than the API's actual rule. A reader may conclude "then I'll just use notebook_params" — which also fails if the job declares job-level parameters. A clause like "and the legacy slots cannot be used at all against a job that declares job-level parameters" would close that gap. Fine to leave for a follow-up.


Drafted-by: Claude Code (Opus 5)

@potiukpotiuk added the ready for maintainer review Set after triaging when all criteria pass. label Jul 28, 2026
@eladkal
eladkal merged commit 52133f1 into apache:mainAug 6, 2026
83 checks passed
dabla pushed a commit to dabla/airflow that referenced this pull request Aug 14, 2026
…owOperator (apache#70130)
* Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator
The DatabricksRunNowOperator always forwards Dag-level parameters as job_parameters, but some Databricks jobs do not expect or accept these parameters, causing task failures. This change introduces a forward_dag_params boolean parameter (defaulting to True) to allow opting out. Additionally, this fixes a Windows-specific encoding issue when parsing imports in static checks, guards the os.register_at_fork calls to prevent startup crashes on Windows, and adds a fcntl mock inside conftest to enable the local test suite on Windows.
* Skip Databricks job_parameters auto-injection when conflicting legacy parameter slots are used
The Databricks API run-now endpoint rejects job_parameters when combined with notebook_params, python_params, jar_params, spark_submit_params, python_named_params, or dbt_commands. This update automatically skips forwarding DAG-level params into job_parameters if any of those conflicting slots are present in the payload. Also updates docstrings, operator RST documentation, and unit tests.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersprovider:databricksready for maintainer reviewSet after triaging when all criteria pass.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DatabricksRunNowOperator always pass parameters to Databricks Job

6 participants

@onlyarnav@eladkal@moomindani@amoghrajesh@jroachgolf84@potiuk
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Providers: Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator - #70130

Merged
eladkal merged 3 commits into
apache:mainfrom
onlyarnav:fix-databricks-run-now-forward-params
Aug 6, 2026
Merged

Providers: Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator#70130
eladkal merged 3 commits into
apache:mainfrom
onlyarnav:fix-databricks-run-now-forward-params

Conversation

@onlyarnav

Copy link
Copy Markdown
Member

Description

This PR introduces an option to opt out of forwarding Dag-level parameters in the DatabricksRunNowOperator.

In PR #66613 (for issue #39002), parameter forwarding was introduced such that the operator's params dict is automatically forwarded as job_parameters when no job_parameters are specified. However, this changes the payload for Databricks jobs and breaks execution for jobs whose entry points do not expect or accept additional parameters.

To resolve this compatibility issue, this PR:

  1. Adds a new boolean parameter forward_dag_params (default: True) to DatabricksRunNowOperator.
  2. Checks self.forward_dag_params when constructing the payload inside _build_run_now_payload before merging self.params.
  3. Adds unit tests to verify that Dag-level parameters are not forwarded when forward_dag_params=False.
  4. Fixes minor Windows-specific issues (e.g. file encoding, os.register_at_fork, and a mock fcntl) to enable executing the local test suite on Windows development hosts.

closes: #70121


Was generative AI tooling used to co-author this PR?
  • Yes (Google Antigravity)

Generated-by: Google Antigravity following the guidelines

@jroachgolf84jroachgolf84 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please review my comments, specifically, there are a few changes in there I don't think should be in there.

Comment threadproviders/databricks/tests/conftest.py
Comment threadscripts/ci/prek/common_prek_utils.py
amoghrajesh
amoghrajesh previously requested changes Jul 20, 2026

@amoghrajeshamoghrajesh left a comment

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.

@onlyarnav there is some unrelated changes in your PR diff, please revise it and keep the changes only scoped to this PR.

Comment threadproviders/databricks/tests/conftest.py Outdated
Comment threadshared/observability/src/airflow_shared/observability/metrics/stats.py Outdated
…owOperator
The DatabricksRunNowOperator always forwards Dag-level parameters as job_parameters, but some Databricks jobs do not expect or accept these parameters, causing task failures. This change introduces a forward_dag_params boolean parameter (defaulting to True) to allow opting out. Additionally, this fixes a Windows-specific encoding issue when parsing imports in static checks, guards the os.register_at_fork calls to prevent startup crashes on Windows, and adds a fcntl mock inside conftest to enable the local test suite on Windows.
@onlyarnav
onlyarnavforce-pushed the fix-databricks-run-now-forward-params branch from 6d0b519 to 340211aCompareJuly 20, 2026 14:49

@jroachgolf84jroachgolf84 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the changes, LGTM.

@eladkal

Copy link
Copy Markdown
Contributor

cc @moomindani for a review from Databricks team

@moomindanimoomindani left a comment

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.

Thanks for the fix, and thanks for cleaning up the unrelated Windows changes — the diff is nicely scoped now.

I validated this against a real Databricks workspace, and the regression is more severe than the issue describes. The run-now endpoint rejects job_parameters outright when combined with any of the legacy param slots. All six confirmed:

job_parameters can not be used in combination with notebook_params
job_parameters can not be used in combination with python_params
job_parameters can not be used in combination with jar_params
job_parameters can not be used in combination with spark_submit_params
job_parameters can not be used in combination with python_named_params
job_parameters can not be used in combination with dbt_commands

Since Dag-level params propagate to the operator implicitly, a Dag like this has been failing since 7.16.0 with no user action:

withDAG("d", params={"env": "prod"}):
DatabricksRunNowOperator(task_id="t", job_id=1, notebook_params={"foo": "bar"})
# payload -> {"job_id": 1, "notebook_params": {...}, "job_parameters": {"env": "prod"}} # API rejects

I also checked whether an escape hatch already existed: job_parameters={} does not work, because not json.get("job_parameters") treats an empty dict as falsy and injects params anyway. So the new flag is genuinely necessary — the approach is right.

Verification I ran:

  • Reverted the guard in _build_run_now_payload → the new test fails. Restored → full operator suite passes (201 tests).
  • prek run --stage pre-commit clean on the diff.

The direction is good. I left three inline notes — the first one is the substantive one (default behaviour still leaves existing users broken); the others are the docstring and test coverage.

One more docs point I could not anchor inline, because the file is not part of this diff: providers/databricks/docs/operators/run_now.rst (the "Forwarding Airflow Dag params as Databricks job parameters" section, around line 60) still documents forwarding as unconditional. That guide is where users land when they hit this failure, so the opt-out should be discoverable there too — a sentence naming forward_dag_params=False, plus the mutual-exclusivity constraint with the legacy param slots.

Non-blocking, out of scope for this PR: #66613 added the same forwarding to DatabricksCreateJobsOperator (parameters) and DatabricksSubmitRunOperator (per-task dict slots), which have no opt-out. Scoping this to RunNow matches the issue, so no change needed here — just flagging it in case the flag should be applied consistently in a follow-up.


Drafted-by: Claude Code (Opus 5)

… parameter slots are used
The Databricks API run-now endpoint rejects job_parameters when combined with notebook_params, python_params, jar_params, spark_submit_params, python_named_params, or dbt_commands. This update automatically skips forwarding DAG-level params into job_parameters if any of those conflicting slots are present in the payload. Also updates docstrings, operator RST documentation, and unit tests.
@onlyarnav
onlyarnavforce-pushed the fix-databricks-run-now-forward-params branch from fa593d3 to 90e726bCompareJuly 27, 2026 13:15

@moomindanimoomindani left a comment

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.

All three addressed, verified by running 90e726b6 rather than reading the summary. The auto-skip is implemented as suggested, and the four paths behave correctly:

Dag params + notebook_params -> {job_id, notebook_params} # regression repaired, no user change
explicit job_parameters + slot -> both preserved # user intent respected
Dag params, no slot -> {job_id, job_parameters} # forwarding still works
forward_dag_params=False -> {job_id} # flag still honoured

Keeping an explicitly-passed job_parameters rather than silently dropping it is the right call — only the implicit forwarding is skipped, so a user who deliberately combined them still gets the API error instead of a silent behaviour change. 207 tests pass, and the test_execute_does_not_mutate_json_template_field edit is a necessary consequence of the skip logic with its assertions intact.

I went back to the workspace to check the approach itself, and found the constraint is bidirectional — worth knowing, though it does not change my assessment:

Job configSentResult
has job-level parametersnotebook_params onlyrejected: "Cannot use legacy parameters (...) because the job has job parameters configured"
has job-level parametersjob_parameters onlyaccepted
no job-level parametersnotebook_params onlyaccepted
eitherbothrejected: "job_parameters can not be used in combination with notebook_params"

So for a job that does declare job-level parameters, skipping the injection trades one rejection for the other. But that combination was already impossible before #66613, so the set of broken Dags is unchanged — and the case your fix actually repairs (job without job-level parameters + legacy slot + Dag params) is a genuine #66613 regression. The skip condition maps correctly onto the API constraint, and forward_dag_params still earns its place for jobs whose entry point rejects extra params even with no slot conflict. Approach looks right to me.

One optional docs nit, non-blocking: the new note says job_parameters cannot be combined with the legacy slots, which is accurate but narrower than the API's actual rule. A reader may conclude "then I'll just use notebook_params" — which also fails if the job declares job-level parameters. A clause like "and the legacy slots cannot be used at all against a job that declares job-level parameters" would close that gap. Fine to leave for a follow-up.


Drafted-by: Claude Code (Opus 5)

@potiukpotiuk added the ready for maintainer review Set after triaging when all criteria pass. label Jul 28, 2026
@eladkal
eladkal merged commit 52133f1 into apache:mainAug 6, 2026
83 checks passed
dabla pushed a commit to dabla/airflow that referenced this pull request Aug 14, 2026
…owOperator (apache#70130)
* Allow opting out of forwarding Dag-level parameters in DatabricksRunNowOperator
The DatabricksRunNowOperator always forwards Dag-level parameters as job_parameters, but some Databricks jobs do not expect or accept these parameters, causing task failures. This change introduces a forward_dag_params boolean parameter (defaulting to True) to allow opting out. Additionally, this fixes a Windows-specific encoding issue when parsing imports in static checks, guards the os.register_at_fork calls to prevent startup crashes on Windows, and adds a fcntl mock inside conftest to enable the local test suite on Windows.
* Skip Databricks job_parameters auto-injection when conflicting legacy parameter slots are used
The Databricks API run-now endpoint rejects job_parameters when combined with notebook_params, python_params, jar_params, spark_submit_params, python_named_params, or dbt_commands. This update automatically skips forwarding DAG-level params into job_parameters if any of those conflicting slots are present in the payload. Also updates docstrings, operator RST documentation, and unit tests.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersprovider:databricksready for maintainer reviewSet after triaging when all criteria pass.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DatabricksRunNowOperator always pass parameters to Databricks Job

6 participants

@onlyarnav@eladkal@moomindani@amoghrajesh@jroachgolf84@potiuk