Skip to content

Subtle footgun in RTKQuery onQueryStarted queryFulfilled usage.Β #2064

@joel1st

Description

@joel1st

This issue is a combination of docs & api design.
The document in question: https://redux-toolkit.js.org/rtk-query/usage/manual-cache-updates

Currently queryFulfilled returns a promise which will resolve to the data or throw an exception.

This introduces a subtle quirk where you are actually handling the same exception in multiple different ways. Both in the hook/unwrap() function as well as the queryFulfilled callback.

For pessimistic updates, The docs (linked above) suggest wrapping the entire function in a try/catch. This is problematic because now any potential issues outside of the queryFulfilled are swallowed away and are very difficult to debug. If you decide to add logging in the catch block, you will be logging any fetch errors as well.

Because of this I removed the try / catch block. A few days later this resulted in a difficult to debug test failure where the fetch error that jest is reporting as 'isUnhandledError: false' is causing an unhandled error without a stack trace. Much time was spent looking at the unwrap code only to realise an embarrassingly long time later that the error is actually being thrown from the onQueryStarted callbacks.

My final resolution was to update every onQueryStarted as seen below:
From:

let res = await queryFulfilled
// ... dispatch logic

To:

let res = await queryFulfilled.catch(e => ({error: e}))
if (error in res) return;
// ... dispatch logic

Obviously this adds a bit of boilerplate, but at least now I am only alerted to errors I should actually be investigating, and also not swallowing errors that I need to look into. {data} | {error} makes sense as a default as you shouldn't need to set up exception handling in multiple places for the same errors. If there is a reason for handling the same exception multiple times, I think the docs should be updated to outline some of the potential issues.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions