-
Notifications
You must be signed in to change notification settings - Fork 16.3k
Description
Apache Airflow version
3.1.0
If "Other Airflow 2/3 version" selected, which one?
No response
What happened?
When using the params parameter in HITL Operator, the behavior is different than the params parameter for DAG even if the Param initially comes from the DAG.
From my tests, at initilization, all param are taken into account, but afterward they seems to loose effect (for validation/UI).
I'm attaching screenshot of resulting UI with the code from the how to reproduce steps.
You can see on this screenshot of the trigger UI that there is number with minimum of 3, a multiline string and a date with a datepicker.

On this screenshot which is the HITL UI, the first three params field come from the trigger params but have lost their UI/formatting/constraints.

I can modify the value as I want e.g. provide a value under minimum for the int param, provide any string for the date param.
to me it seems that:
- all arguments of Param beside the type and default value are ignored in the HITL operators beside at initialization where for example I can't give a default of 2 for a number if I set a minimum of 3.
- The default value does not have the same behavior either.
- example: This is valid Param(type="string", format="date-time") at DAG level, but not for HITLEntryOperator
What you think should happen instead?
I was expecting providing the same Param to the params argument have the same UI/validation behavior as providing them to the DAG in the params arguments.
And that the one inherited from the dag params would be the same when I trigger and in the HITL
How to reproduce
You can reproduce the issue with the following DAG: in an airflow 3.1+ instance.
import datetime
import pendulum
from airflow import DAG
from airflow.providers.standard.operators.hitl import ApprovalOperator, HITLBranchOperator, \
HITLEntryOperator, HITLOperator
from airflow.sdk import BaseNotifier, Context, Param, task
class LocalLogNotifier(BaseNotifier):
"""Simple notifier to demonstrate HITL notification without setup any connection."""
template_fields = ("message",)
def __init__(self, message: str) -> None:
self.message = message
def notify(self, context: Context) -> None:
url = HITLOperator.generate_link_to_ui_from_context(
context=context,
base_url="http://localhost:28080",
)
self.log.info(self.message)
self.log.info("Url to respond %s", url)
hitl_request_callback = LocalLogNotifier(
message="""
[HITL]
Subject: {{ task.subject }}
Body: {{ task.body }}
Options: {{ task.options }}
Is Multiple Option: {{ task.multiple }}
Default Options: {{ task.defaults }}
Params: {{ task.params }}
"""
)
hitl_success_callback = LocalLogNotifier(
message="{% set task_id = task.task_id -%}{{ ti.xcom_pull(task_ids=task_id) }}"
)
hitl_failure_callback = LocalLogNotifier(message="Request to response to '{{ task.subject }}' failed")
with DAG(
dag_id="example_hitl_operator",
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
params={
"Number param": Param("", type="number", minimum=3),
"multiline param": Param("", type="string", format="multiline"),
"Date param": Param(type="string", format="date-time"),
},
catchup=False,
tags=["example", "HITL"],
):
pass
wait_for_input = HITLEntryOperator(
task_id="wait_for_input",
subject="Please provide required information: ",
# Same as Dag params but with different name to make sure there is no collision
params={
# We can't have an empty value, we have to provide a number that also respect the minimum criteria or operator will fail
"Number param2": Param(3, type="number", minimum=3),
"multiline param2": Param("", type="string", format="multiline"),
# We also have to provide something in a datetimeformat here, we can't leave it empty
"Date param2": Param(str(datetime.datetime.now()), type="string", format="date-time"),
},
notifiers=[hitl_request_callback],
on_success_callback=hitl_success_callback,
on_failure_callback=hitl_failure_callback,
)Operating System
Debian GNU/Linux 12 (bookworm) (docker container, main OS ubuntu 24.04)
Versions of Apache Airflow Providers
apache-airflow-providers-celery==3.12.4
apache-airflow-providers-common-compat==1.7.4
apache-airflow-providers-common-io==1.6.3
apache-airflow-providers-common-sql==1.28.1
apache-airflow-providers-elasticsearch==6.3.3
apache-airflow-providers-openlineage==2.7.2
apache-airflow-providers-smtp==2.3.1
apache-airflow-providers-standard==1.9.0
Deployment
Astronomer
Deployment details
Local deployment created using astro dev init and then run using astro dev run
source dockerfile is astrocrpublic.azurecr.io/runtime:3.1-2
Anything else?
No response
Are you willing to submit PR?
- Yes I am willing to submit a PR!
Code of Conduct
- I agree to follow this project's Code of Conduct