#Error: Invariant: static generation store missing in revalidateTag

1 messages · Page 1 of 1 (latest)

quasi prairieBOT
#

Hi @bitter pike. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

The error message "Invariant: static generation store missing in revalidateTag" suggests that there's an issue with the revalidation process in your Next.js application. This error is likely due to the way the revalidateTag function is being used.

From the knowledge sources, it's clear that revalidateTag is a function provided by Next.js for revalidating data in the cache. However, it seems that some users have reported issues with its reliability, especially when it's called via a route. Some users have reported that revalidateTag does not always clear the cache successfully, especially for server-side fetch() calls (source (https://github.com/vercel/next.js/issues/60834)).

In your case, it seems that the revalidateTag function is being called after fetching the CMS API token. If the fetch operation fails or if the token is not properly cached, this could potentially lead to the error you're seeing.

One thing to note is that if an error is thrown while attempting to revalidate data, the last successfully generated data will continue to be served from the cache. On the next subsequent request, Next.js will retry revalidating the data (source (https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#error-handling-and-revalidation)).

As a first step, you might want to ensure that the fetch operation is successful and that the CMS API token is properly cached before calling revalidateTag. If the issue persists, it might be worth considering alternative strategies for data fetching and caching, or reaching out to the Next.js community for further assistance.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@bitter pike kapa.ai is still learning and improving, please let us know how it did by reacting below

bitter pike
#

@quasi prairie how can i ensure that the CMS API token is properly cached before calling revalidateTag?

quasi prairieBOT
#

Let me check the knowledge base for you. One moment! :books:

#

To ensure that the CMS API token is properly cached before calling revalidateTag, you can follow these steps:

  1. Check the response from the fetch operation: Ensure that the fetch operation to get the CMS API token is successful and that the response contains the expected data. You can do this by checking the status of the response and the structure of the data.
const response = await fetch(`${CMS_URL}/api/1/access_token`, {
  headers: CONTENT_TYPE_HEADER,
  method: 'POST',
  body: JSON.stringify({
    apiLogin: CMS_API_KEY,
  }),
  cache: 'force-cache',
  next: { tags: ['cms-api-token'] },
});

if (!response.ok) {
  throw new Error(`Fetch operation failed with status: ${response.status}`);
}

const responseData: GetCmsApiTokenResponseData = await response.json();
if (!responseData.token) {
  throw new Error(`Bad CMS response: ${JSON.stringify(responseData)}`);
}
  1. Use the Next.js cache API: Next.js provides a cache API that you can use to cache data. You can use the set method to cache the CMS API token and the get method to retrieve it. If the get method returns the expected data, you can be sure that the data is properly cached.
import { cache } from 'next/cache';

// Cache the CMS API token
cache.set('cms-api-token', responseData.token);

// Retrieve the CMS API token from the cache
const cachedToken = cache.get('cms-api-token');

if (!cachedToken) {
  throw new Error('CMS API token not found in cache');
}
  1. Call revalidateTag: Once you've confirmed that the CMS API token is properly cached, you can safely call revalidateTag.
try {
  revalidateTag('cms-api-token');
} catch (error) {
  console.log('Failed to revalidate tag', error);
}
#

@bitter pike kapa.ai is still learning and improving, please let us know how it did by reacting below

bitter pike
#

@quasi prairieIn my app, I have a function that fetches the CMS API token. Many of my server actions, such as getCustomerInfo, require an up-to-date API token to successfully fetch data. The API token has a lifetime of 60 minutes. If I call the function that fetches the token in every server action that needs it, it works fine. However, if I want to cache the token for 50 minutes to decrease the number of CMS API calls, I face a problem. After 50 minutes have passed, the function that fetches the API token will return a stale token on the first call, and only subsequent calls will give a fresh token after revalidation occurs untill next revalidation period. This issue occurs due to the stale-while-revalidate policy, but it is not suitable in this case because the function returning a stale token will lead to the failure of server actions that rely on the CMS API token. What is the best and optimal solution to this problem?

quasi prairieBOT
#

Let me check the knowledge base for you. One moment! :books:

#

The issue you're facing is a common one when dealing with tokens or any data that has an expiration time. The stale-while-revalidate policy can indeed cause problems in this case, as it may serve stale data while revalidating in the background.

One solution to this problem is to implement a mechanism that refreshes the token before it expires. Here's a general approach:

  1. Fetch the token and store it in the cache: When you fetch the token, store it in the cache along with the current time.
import { cache } from 'next/cache';

const response = await fetch(`${CMS_URL}/api/1/access_token`, {
  headers: CONTENT_TYPE_HEADER,
  method: 'POST',
  body: JSON.stringify({
    apiLogin: CMS_API_KEY,
  }),
  cache: 'force-cache',
  next: { tags: ['cms-api-token'] },
});

const responseData: GetCmsApiTokenResponseData = await response.json();
if (!responseData.token) {
  throw new Error(`Bad CMS response: ${JSON.stringify(responseData)}`);
}

// Store the token and the current time in the cache
cache.set('cms-api-token', {
  token: responseData.token,
  fetchedAt: Date.now(),
});
  1. Check the token's age before using it: Before using the token, check how long ago it was fetched. If it's close to expiring, fetch a new one.
const cachedData = cache.get('cms-api-token');

if (!cachedData) {
  throw new Error('CMS API token not found in cache');
}

const { token, fetchedAt } = cachedData;
const age = Date.now() - fetchedAt;

// If the token is older than 50 minutes, fetch a new one
if (age > 50 * 60 * 1000) {
  // Fetch a new token and store it in the cache
  // ...
}

This approach ensures that you always have a fresh token when you need it, without having to fetch a new one for every server action. However, it does require you to manually manage the token's lifetime, which can add some complexity to your code.