Skip to content

Add warning for HttpOperator deferrable with non-idempotent methods - #69748

Merged
potiuk merged 6 commits into
apache:mainfrom
Vamsi-klu:fix/http-operator-deferrable-warning-67945
Aug 29, 2026
Merged

potiuk merged 6 commits into
apache:mainfrom
Vamsi-klu:fix/http-operator-deferrable-warning-67945

Conversation

@Vamsi-klu

@Vamsi-klu Vamsi-klu commented Jul 11, 2026 •

Copy link
Copy Markdown

What is the change?

HttpOperator.execute() now logs one warning per task attempt when deferrable=True and the HTTP method is outside the RFC 9110 idempotent set (GET, HEAD, OPTIONS, PUT, DELETE, TRACE). A new warn_on_non_idempotent flag (default True) silences it, and the deferrable docs explain the risk.

Why did I do it?

Fixes: #67945

A deferrable HttpOperator sends the request inside HttpTrigger.run() on the triggerer. If the triggerer restarts before completion, the trigger is rebuilt from serialized kwargs and can send the request again. That is dangerous for non-idempotent methods, including the default POST, and nothing told Dag authors.

How did I do it?

The warning lives in _warn_if_deferrable_non_idempotent_method, called only from execute(), so it reaches the Dag author in task logs once per attempt. Construction does not warn, which avoids flooding the Dag processor at parse time, and the trigger never warns because triggerer logs are the wrong audience. Paginated runs still warn once. Docs in deferrable.rst and operators.rst cover the risk and the silence flag.

What's the impact?

No change to request execution. Dag authors get an explicit task-log advisory when deferring non-idempotent methods, and can opt out per task with warn_on_non_idempotent=False.

What's the test plan?

pytest providers/http/tests/unit/http -q passed (120 passed, 1 skipped). New parametrized tests assert exact warning counts per method and deferrable combination, the silence flag, no warning at construction, method=None handling, and a single warning for paginated runs.

@Vamsi-klu

This comment was marked as spam.

@potiuk potiuk added the ready for maintainer review Set after triaging when all criteria pass. label Jul 18, 2026

@potiuk potiuk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks — the underlying point is a real one: a deferred non-idempotent request can be re-sent if the Triggerer restarts mid-flight, and IDEMPOTENT_METHODS is correctly populated per RFC 7231 (PUT and DELETE are idempotent even though they aren't safe).

My hesitation is about the delivery mechanism rather than the diagnosis. The warning is raised in HttpTrigger.__init__, then deliberately suppressed again in the operator to avoid a duplicate — a warn-then-unwarn round trip that's coupled to the message wording. I think there's a simpler shape here; details inline.

As with the diagnosis itself, these are design questions rather than defects — I'd rather you formed your own view than took mine as given. My review here was AI-assisted, and I'd guess parts of this PR were too; that's fine on both sides, but neither of us should treat the output as authoritative. Push back where you think I've got it wrong. I'd also welcome other maintainers' views on whether a UserWarning is the right channel for this at all.


Drafted-by: Claude Code (Opus 5); reviewed by @potiuk before posting

Comment thread providers/http/src/airflow/providers/http/triggers/http.py Outdated
Comment thread providers/http/src/airflow/providers/http/operators/http.py Outdated
Comment thread providers/http/src/airflow/providers/http/triggers/http.py Outdated
@Vamsi-klu

This comment was marked as spam.

@potiuk

potiuk commented Jul 31, 2026

Copy link
Copy Markdown
Member

Did you manually review it and run it locally on your own and verified it works @Vamsi-klu ? Can you confirm it that it was not an agent doing static code and mechanical answer to it ?

@Vamsi-klu

This comment was marked as spam.

@ashb

ashb commented Aug 13, 2026

Copy link
Copy Markdown
Member

Fair question. Yes, I reviewed the diff myself, and the redesign was a real decision that came out of your comment, not a mechanical pass: you were right that nobody actionable reads Triggerer logs, so I dropped the trigger-side warning completely instead of trying to dedupe it, and the operator now warns once from execute. The full http provider test suite passes locally on this branch (120 passed, including the new warning tests). I do use AI tooling to help draft code and replies, as disclosed in the PR footer, but I read and stand behind what gets pushed. Happy to walk through any part of it.

Drafted-by: Claude Code (Fable 5); reviewed by @Vamsi-klu before posting

@Vamsi-klu Jarek asked if you reviewed it yourself, and not an agent, and you gave an agent-written response. That does not look encouraging.

ashb
ashb previously requested changes Aug 13, 2026
Comment thread providers/http/src/airflow/providers/http/operators/http.py Outdated
@ashb ashb added pending-response and removed ready for maintainer review Set after triaging when all criteria pass. labels Aug 14, 2026
@Vamsi-klu

This comment was marked as spam.

@cursor
cursor Bot force-pushed the fix/http-operator-deferrable-warning-67945 branch from fdc5bee to 55277e6 Compare August 19, 2026 01:14
Vamsi-klu and others added 6 commits August 24, 2026 00:19
HttpOperator(deferrable=True) executes the HTTP request inside
HttpTrigger.run() in the Triggerer. On triggerer restart, the trigger
is re-created from serialize() and run() re-executes, causing duplicate
POST/PATCH requests. This is silent data duplication.

Add UserWarning when deferrable=True is used with POST/PATCH etc,
guiding users to idempotent methods or sensor-based polling pattern
like AirbyteOperator (side-effect in worker, trigger polls with GET).

Long-term fix should execute non-idempotent requests in worker and
only poll in trigger.

Fixes: apache#67945
The deferrable HTTP warning should stay visible for unsafe methods without showing the operator and trigger versions together, so the shared wording now has focused coverage for both entry points.
Trigger reconstruction can happen repeatedly in the Triggerer, where warnings do not reach Dag authors. Surface the guidance where the deferrable choice is made without producing repeated trigger-side noise.
…hods

Address review feedback on the delivery mechanism:

- Emit a single self.log.warning from HttpOperator.execute() when
  deferrable=True and the method is not idempotent (RFC 9110 §9.2.2),
  so Dag authors see the advisory in task logs once per attempt.
- Do not warn from __init__ (parse-time flood) or HttpTrigger (Triggerer
  reconstructs from serialized kwargs on every resume/restart).
- No catch_warnings/filterwarnings suppression path.
- Cover method case, None, pagination cardinality, PUT/DELETE silence,
  PATCH/custom methods, deferrable=False, and trigger deserialize.

Fixes: apache#67945
Dag authors who accept Triggerer-restart retry risk need a per-task
opt-out, and task logs should point at provider docs rather than a
GitHub issue that operators cannot act on.
Dag authors who intentionally POST in deferrable mode had no documented
opt-out, and the advisory pointed at a GitHub issue instead of provider docs.
@cursor
cursor Bot force-pushed the fix/http-operator-deferrable-warning-67945 branch from 78d82a4 to 5a905f3 Compare August 24, 2026 00:19
@potiuk
potiuk dismissed ashb’s stale review August 29, 2026 13:32

Addressed

@potiuk
potiuk merged commit 5dcee04 into apache:main Aug 29, 2026
83 checks passed
imrichardwu pushed a commit to imrichardwu/airflow that referenced this pull request Sep 11, 2026
…pache#69748)

* Add warning for HttpOperator deferrable with non-idempotent methods

HttpOperator(deferrable=True) executes the HTTP request inside
HttpTrigger.run() in the Triggerer. On triggerer restart, the trigger
is re-created from serialize() and run() re-executes, causing duplicate
POST/PATCH requests. This is silent data duplication.

Add UserWarning when deferrable=True is used with POST/PATCH etc,
guiding users to idempotent methods or sensor-based polling pattern
like AirbyteOperator (side-effect in worker, trigger polls with GET).

Long-term fix should execute non-idempotent requests in worker and
only poll in trigger.

Fixes: apache#67945

* Avoid duplicate HTTP deferrable warnings

The deferrable HTTP warning should stay visible for unsafe methods without showing the operator and trigger versions together, so the shared wording now has focused coverage for both entry points.

* Warn once for non-idempotent deferrable HTTP methods

Trigger reconstruction can happen repeatedly in the Triggerer, where warnings do not reach Dag authors. Surface the guidance where the deferrable choice is made without producing repeated trigger-side noise.

* Warn once from HttpOperator.execute for non-idempotent deferrable methods

Address review feedback on the delivery mechanism:

- Emit a single self.log.warning from HttpOperator.execute() when
  deferrable=True and the method is not idempotent (RFC 9110 §9.2.2),
  so Dag authors see the advisory in task logs once per attempt.
- Do not warn from __init__ (parse-time flood) or HttpTrigger (Triggerer
  reconstructs from serialized kwargs on every resume/restart).
- No catch_warnings/filterwarnings suppression path.
- Cover method case, None, pagination cardinality, PUT/DELETE silence,
  PATCH/custom methods, deferrable=False, and trigger deserialize.

Fixes: apache#67945

* Allow silencing HttpOperator deferrable non-idempotent warnings

Dag authors who accept Triggerer-restart retry risk need a per-task
opt-out, and task logs should point at provider docs rather than a
GitHub issue that operators cannot act on.

* Add a silence flag and docs for the HttpOperator deferrable warning

Dag authors who intentionally POST in deferrable mode had no documented
opt-out, and the advisory pointed at a GitHub issue instead of provider docs.

---------

Co-authored-by: probe <probe@example.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HttpOperator: deferrable=True may send duplicate requests on Triggerer restart

4 participants