fix(api): revert approval to pending when resume fails to start - #6384
fix(api): revert approval to pending when resume fails to start#6384lorenzozanee wants to merge 1 commit into
Conversation
Answering a pending approval currently marks the row as responded before the detached workflow run is known to have started. If the workflow service returns 500 or the enqueue fails, the approval is consumed and the human has no way to retry, with no visible error on the row. Revert the interaction to pending with the error recorded in resolution and surface a 502 so the caller knows the run never started. For the async worker path, revert only on the final retry so concurrent retries cannot double-enqueue. Closes Agenta-AI#5592
|
@lorenzozanee is attempting to deploy a commit to the agenta projects Team on Vercel. A member of the Team first needs to authorize it. |
|
✅ Thanks @lorenzozanee! This PR now meets the contribution requirements and has been reopened. A maintainer will review it soon. |
|
|
mmabrouk
left a comment
There was a problem hiding this comment.
thanks for the pr. i found one issue that needs a change before qa.
| request=invoke_request, | ||
| ) | ||
| except Exception as exc: # noqa: BLE001 — revert answered gate so retry stays possible | ||
| err = str(exc)[:500] or exc.__class__.__name__ |
There was a problem hiding this comment.
The exception text is not safe to return or persist here. WorkflowDetachedStartFailed includes up to 500 bytes of the runner's raw response body (workflows/service.py:734-737), and this value is copied into both resolution.error and the HTTP 502 detail. A failed resume can therefore expose internal response data to the project user and retain it in the interaction row. Log the original exception server-side, but store and return a stable sanitized message, with a support ID if needed. Apply the same sanitization in interactions_worker.py.
Summary
Answering a parked approval marks the row as
respondedbefore the resumed run is known to have started. When the workflow service returns 500 or the enqueue fails, the approval is lost — the run never starts and there is no way to retry.This change reverts the row to
pendingwith the error stored inresolutionand returns 502 so the approval remains actionable and the failure is visible. For the async worker path, the revert happens only on the final retry to avoid races with concurrent retries. Also fixes watch publishing to emitpendingon revert.Fixes #5592.
Testing
Verified locally
pytest oss/tests/pytest/unit/sessions/test_respond_interaction_resume_failure.py— 4 new tests (inline invoke, dispatcher, kiq enqueue failure, and success path)pytest oss/tests/pytest/unit/sessions/test_respond_interaction_enqueue.py— 3 existing tests still passruff format/ruff check— cleanAdded or updated tests
api/oss/tests/pytest/unit/sessions/test_respond_interaction_resume_failure.py— covers three enqueue paths reverting topendingwith 502 and the success path stayingresponded.QA follow-up
pendingwithresolution.error.responded/resolved.Demo
API-only fix — approval resume failure is backend behavior. Screenshot of the new regression tests passing locally and the 502 revert behavior:
https://github.com/user-attachments/assets/demo-approval-revert.mp4
Checklist