Skip to content

[backport v2.14.1] Guard against unhandled exceptions when using waitFor()#17086

Merged
rak-phillip merged 2 commits into
release-2.14from
gha-portpr-23810081310-1
Apr 3, 2026
Merged

[backport v2.14.1] Guard against unhandled exceptions when using waitFor()#17086
rak-phillip merged 2 commits into
release-2.14from
gha-portpr-23810081310-1

Conversation

@rancher-ui-project-bot
Copy link
Copy Markdown

@rancher-ui-project-bot rancher-ui-project-bot Bot commented Mar 31, 2026

This is an automated request to port PR #17034 by @rak-phillip

fixes #16791

Original PR body:

Summary

This change resolves issues surrounding permanently hung promises when unhandled exceptions are thrown by waitFor(). This change aims to reduce the number of scenarios where developers can inadvertently cause promises to hang(cede2d3) while also adding some additional safety nets in the event that an unhandled exception is raised(21e08935b346c71d2e2b6f00274add8b1812c490)

Original text redacted by port-pr.yaml

Occurred changes and/or fixed issues

  • Always reject regardless of message passed to waitFor()
  • Guard against unhandled exceptions using waitFor()

Technical notes summary

Permanently hung promises are prevented by always rejecting regardless whether a message was passed to waitFor(). Switching to a throw when a message is omitted subverts expectations and is prone to error if a developer does not anticipate this change in behavior. Relying on reject is more predictable and will properly propagate through the Promise chain.

This also adds some guards to resolve issues with waitForSettingsSchema and waitForSettings where unhandled exceptions can cause the promise chain to hang. When in this state, promises are permanently unresolved and users are unable to interact with certain links throughout Dashboard.

  • Add msg parameters to waitForSettingsSchema and waitForSettings so that timeouts will reject with a clear message
  • Wrap both calls to waitForSettingsSchema and waitForSettings in a try..catch block so that the worker can be cleaned up instead of risking blocking the caller
  • Return early instead of throwing a null reference error on postMessage so that allHashSettled can safely settle

Areas or cases that should be tested

The existing behavior can be tested more quickly by setting timeoutMs to some incredibly low value: timeoutMs = 50000

https://github.com/rak-phillip/dashboard/blob/f0c2fb0089fab197bb24d3479f638edf7af2968f/shell/utils/async.ts#L1

I also set several auth ttl values to low values so that we can speed up the automatic logout behavior:

image

In order to assert that this change works. First, set up your environment so that you can easily repro in master. Second, checkout this change with the same repro previously performed. We can expect two behaviors:

  1. An absence of an error printed to the console:
    Uncaught Error: waitFor timed out after 50 seconds
     timeout async.ts:16
     setTimeout handler*./shell/utils/async.ts/waitFor/< async.ts:9
     waitFor async.ts:4
     waitForSettingsSchema subscribe.js:134
     createWorker subscribe.js:198
     steveStoreInit index.js:62
     __WEBPACK_DEFAULT_EXPORT__ index.js:51
     Store vuex.esm-bundler.js:958
     Store vuex.esm-bundler.js:958
     createStore vuex.esm-bundler.js:897
     extendStore store.js:87
     extendApp app-extended.js:37
     js entry.js:33
    
  2. After logging in, the links in question function as expected

Areas which could experience regressions

I think there are some risks in modifying the behavior of our websocket connections. Most notably, I can be incorrect about my assumptions in how to properly clean up workers in 21e08935b346c71d2e2b6f00274add8b1812c490.

Screenshot/Video

NA - the demonstrable change is of hard to prove with video/screenshots. I highly recommend a repro to assert that the issue is resolved.

Checklist

  • The PR is linked to an issue and the linked issue has a Milestone, or no issue is needed
  • The PR has a Milestone
  • The PR template has been filled out
  • The PR has been self reviewed
  • The PR has a reviewer assigned
  • The PR has automated tests or clear instructions for manual tests and the linked issue has appropriate QA labels, or tests are not needed
  • The PR has reviewed with UX and tested in light and dark mode, or there are no UX changes
  • The PR has been reviewed in terms of Accessibility
  • The PR has considered, and if applicable tested with, the three Global Roles Admin, Standard User and User Base

This helps to prevent permanently hung promises by always rejecting regardless whether a message was passed to `waitFor()`. Switching to a `throw` when a message is omitted subverts expectations and is prone to error if a developer does not anticipate this change in behavior.  Relying on reject is more predictable and will properly propagate through the Promise chain.

Signed-off-by: Phillip Rak <rak.phillip@gmail.com>
This adds some guards to resolve issues with `waitForSettingsSchema` and `waitForSettings` where unhandled exceptions can cause the promise chain to hang. When in this state, promises are permanently unresolved and users are unable to interact with certain links throughout Dashboard.

- Add msg parameters to `waitForSettingsSchema` and `waitForSettings` so that timeouts will reject with a clear message
- Wrap both calls to `waitForSettingsSchema` and `waitForSettings` in a try..catch block so that the worker can be cleaned up instead of risking blocking the caller
- Return early instead of throwing a null reference error on `postMessage` so that `allHashSettled` can safely settle

Signed-off-by: Phillip Rak <rak.phillip@gmail.com>
@rak-phillip rak-phillip merged commit 95f4a7e into release-2.14 Apr 3, 2026
38 checks passed
@rak-phillip rak-phillip deleted the gha-portpr-23810081310-1 branch April 3, 2026 20:51
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.

[backport v2.14.1] UI Links Unclickable After Login After Session Timeout

2 participants