Next.js Discord

Discord Forum

try/catch inside function cached with unstable_cache is not working as expected when throwing error

Unanswered
Transvaal lion posted this in #help-forum
Open in Discord
Avatar
Transvaal lionOP
I have run into a weird caching issue.

I have a function

export const getContentfulPageBySlugLoader = cache((locale: string, slug: string) =>
    unstable_cache(
        async () => {
            try {
                const page = await getContentfulPageBySlug(locale, slug);

                return page;
            } catch (err: any) {
                console.error(err);
                throw err; // <- This is the problem
            }
        },
        [locale, slug],
        { revalidate: 60, tags: ["page"] },
    )(),
);


It works fine when I just change some fields, but if I publish and unpublish it does not work (in the production build, in dev mode it does).

The reason has to be that if I unpublish en entry in Contentful it returns null and my code will throw an exception, which is caught here - and if rethrown, the unpublish will never carry over - it'll just continue to show the page as if it was still published.

Since getContentfulPageBySlug also throws an exception (NotFoundError) it also doesn't work if I omit try catch since it gets implicitly thrown then. Same as if I have the try/catch and rethrows the error.

It only works if I have try/catch and do not rethrow the error from the cached function.

4 Replies

Avatar
Transvaal lionOP
Is the only solution to convert the exception to an error object and return that in the catch clause?

} catch (err: any) {
    console.error(err);
    return {
        error: {
            message: err.message,
            status: err.status,
        },
    };
}
Avatar
Transvaal lionOP
anyone? 😄
Is this a bug in Next?
I could live with the fact that it holds onto the last successful cached entry if an exception occurs, as long as it would honor the revalidate period that was set. It doesn't - it keeps caching it - outside the revalidation period also.