Skip to content

fix(serve): raise PollingTimeoutError instead of hanging in AsyncPredictor - #6412

Open
AkshayShah03 wants to merge 1 commit into
aws:masterfrom
AkshayShah03:fix/async-predictor-waiter-timeout
Open

AkshayShah03 wants to merge 1 commit into
aws:masterfrom
AkshayShah03:fix/async-predictor-waiter-timeout

Conversation

@AkshayShah03

Copy link
Copy Markdown

Issue #, if available: N/A

Description of changes:

AsyncPredictor._check_output_and_failure_paths runs two S3 object_exists waiters, one for the output file and one for the failure file, then loops until either one is found:

while not output_file_found.is_set() and not failure_file_found.is_set():
    time.sleep(1)

If both waiters give up, raising WaiterError after max_attempts * delay, neither event is set. The loop then spins forever, so predict() on an async endpoint never returns and the PollingTimeoutError branch is unreachable. That branch also called get_object on the failure key before checking that the file existed.

This change:

  • exits the loop once both waiter threads have finished;
  • raises AsyncInferenceModelError only when the failure file was found, and PollingTimeoutError otherwise.

v2 fixed the hang in #4951 with a "waiter error" event. That version stops as soon as either waiter fails, so a failure file that appears just after the output waiter times out gets reported as a timeout. Waiting on thread liveness avoids that.

Testing:

  • test_raises_polling_timeout_when_both_waiters_time_out: hangs before this change. The test runs the call in a daemon thread with a join timeout, so a hang fails the test instead of the suite.
  • test_raises_model_error_when_failure_file_appears_after_output_waiter_times_out.
  • tests/unit/test_predictor_async.py: 18 passed.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

…ictor

_check_output_and_failure_paths waited in a loop until either the output or
the failure file was found. When both S3 waiters gave up (WaiterError after
max_attempts * delay), neither event was set and the loop spun forever, so
predict()/the wait on an async endpoint never returned, and the
PollingTimeoutError branch was unreachable. That branch also fetched the
failure object before checking whether it existed.

Exit the loop once both waiter threads have finished, raise
AsyncInferenceModelError only when the failure file was found, and
PollingTimeoutError otherwise. v2 handles this case (aws#4951); unlike v2, this
keeps waiting for the failure waiter if only the output waiter has timed out,
so a model error that lands slightly later is still reported as such.

This branch had an error being deployed

1 failed deployment
manual-approval — aed8f9a9 Deployed Oct 9, 2026 by AkshayShah03 via wait-for-approval #1688
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant