Problem encountered while revalidating Next.js and Sanity documents through a webhook

I'm currently developing a Next.js 13 project that utilizes Sanity as its CMS and is deployed on Vercel. To ensure that components and pages are revalidated whenever a new testimonial is added, updated, or removed in Sanity, I have configured a webhook. However, I am facing a TypeError stating "resolver is not a function," and I am uncertain how to resolve this issue.

Below is the code snippet for the webhook:

import { SIGNATURE_HEADER_NAME, isValidSignature } from "@sanity/webhook";

const handler = async (req: any, res: any) => {
    try {
        const signature = req.headers[SIGNATURE_HEADER_NAME].toString();
        if (
            !isValidSignature(
                JSON.stringify(req.body),
                signature,
                process.env.NEXT_PUBLIC_SECRET_TOKEN as string
            )
        ) {
            return res.status(401).json({ message: "Invalid request" });
        }
        await res.revalidate("/");
        res.status(200).json({ revalidated: true });
        console.log("testimonial revalidated");
        
    } catch (error) {
        res.status(500).json({ revalidated: false, error });
    }
};

The error message I am encountering reads:

TypeError: resolver is not a function
    at /var/task/node_modules/next/dist/server/api-utils/node.js:463:16
    // ...

I suspect that the error could be related to the usage of the res.revalidate function or potentially an issue with my imports. Can someone offer guidance on correctly configuring the webhook to trigger revalidation upon updates from Sanity?

Additional Details:

  • I am using Next.js version 13 with the new app directory structure.
  • The @sanity/webhook package is being employed for managing the webhook functionality.
  • The webhook must initiate revalidation of components and pages when changes occur in Sanity documents.
  • The revalidation should specifically occur without necessitating a complete project rebuild, only when there are updates in Sanity.

Update:

Progress has been made regarding the initial issue of "resolver is not a function," which was attributed to a missing export for the function. Nevertheless, a new challenge has emerged. Upon sending a request to the API, consistently receiving a "401 Unauthorized" response along with the following message:

{
  "message": "Invalid request"
}

Despite trying different approaches such as defining the signature and secret token within the code directly, the same outcome persists. It appears that the webhook is struggling to properly authenticate the requests.

Answer №1

It appears that the signature validation is being tampered with. Ensure that you correctly input the validation secret in both your Sanity webhook and environment variables.

I can provide my code as an example of how I approached this, utilizing the app router:

import { revalidateTag } from "next/cache";
import { type NextRequest, NextResponse } from "next/server";
import { parseBody } from "next-sanity/webhook";

export async function POST(req: NextRequest) {
  try {
    const { isValidSignature, body } = await parseBody<{ _type: string }>(
      req,
      process.env.SANITY_REVALIDATE_SECRET
    );
    
    if (!isValidSignature) {
      const message = "Invalid signature";
      return new Response(JSON.stringify({ message, isValidSignature, body }), {
        status: 401,
      });
    }
    
    if (!body?._type) {
      revalidateTag("page");
    } else {
      revalidateTag(body?._type);
    }
    
    return NextResponse.json({ body });

  } catch (err) {
    console.error(err);
    return new Response(JSON.stringify(err), { status: 500 });
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Only display the element if there is corresponding data available

I have implemented the angular ng-hide directive to conceal certain markup when there is no data present: <li class="header" ng-hide = " todayRecents.length === 0 ">today</li> At this point, ng-hide simply applies a display value of 'non ...

Utilizing variable query operators solely in instances where they hold value

Imagine you are on a movie website where you can customize filters for the movies displayed to you. Currently, these preferences are stored in the User model as a map. Here is an example of what the preferences object might look like: preferences: { yea ...

"Make your slides smooth and responsive with the unslick option in slick

Currently implementing the Slick Slider on a WordPress website. The slider is designed to display 3 columns at a screen size of 1024px and above. When the screen size drops below 1024px, the slider adjusts to show 2 columns, and on mobile devices, it swit ...

What is the best way to refetch data post-creation when working with Prisma in NextJS?

While my data is being loaded at build time using the getStaticProps method, I am faced with a scenario where I need to create new data through a form submission: const handleSubmit = async ({ name, score }) => { const body = { name, email } await f ...

Malfunctioning Bootstrap collapse feature

I am experiencing an issue with my modal that contains 2 blocks. When I click on the .emailInbound checkbox, it opens the .in-serv-container, but when I click on the .accordion-heading to reveal the comment section, the .in-serv-container collapses. What c ...

Adjust the quantity of divs shown depending on the value entered in a text input field

It seems like I am on the right track, but there is something simple that I am missing. I'm currently utilizing the jQuery knob plugin to update the input field. $('document').ready(function() { $(".knob").knob({ c ...

Tips for refreshing a React component following an update with Redux and hooks

Currently, I am working on a next.js page that includes the following code: const Index: NextPage = () => { const state = useSelector((state) => state); useEffect(() => { // API call to fetch comments list and store data using use ...

The Next.js middleware, specifically NextRequest.nextUrl.locale, will return an empty string once it is deployed

Encountering a bug in the next-js middleware The middleware function is returning a NextRequest param According to the documentation from Next.js: The NextRequest object is an extension of the native Request interface, with the following added metho ...

"Error: imports are undefined" in the template for HTML5 boilerplate

After setting up an HTML5 Boilerplate project in WebStorm, I navigate to the localhost:8080/myproject/src URL to run it. Within the src folder, there is a js directory structured like this: libraries models place.model.ts place.model.js addr ...

Tips for integrating a back button functionality with AJAX requests

My single page web application allows users to enter genre, date range, and other inputs before making an ajax post request to a Java Spring MVC server. Despite everything working well, I now want to implement a back functionality. If a user wants to go b ...

Issue with a variable within an *.ejs file

Currently, I am following a guide found at this link, and everything is working smoothly except when I encounter an error on the login screen: ..... 7| >> 8| <% if (message != null) { %> 9| <%= message %> 10| <% } %> 11| message is not defined ...

Server-side authentication issue with AWS Cognito in NextJS using Amplify

I have implemented Cognito for authenticating my app. Everything works fine in the local environment when I run yarn dev, yarn build, and yarn start. However, in the Amplify server deployment, the SSR authentication is not functioning correctly as it alwa ...

Exploring the process of updating initialState within react-redux

I am currently using react-redux to retrieve data from a MongoDB database and integrate it into my React App. Below is the structure I am working with: const initialState = { Level: [{ wId: Math.random(), Level1: [ { id: Math.rando ...

Obtaining a JSON reply using Ember

Exploring new possibilities with Ember js, I am eager to switch from fixtures to using an API. Below is the code I have implemented to fetch the data: App.ItemsRoute = Ember.Route.extend({ model: function() { return $.getJSON('http://som ...

Is it possible in Angular to generate a module and component without including a CSS file in a single command?

Is it possible to generate a Module linked to a component without automatically creating a css file? For example, the default method I've been using involves: ng generate module name / ng generate component name This results in the typical componen ...

Passing information from a directive to a controller using AngularJS

I am looking to display the progress of a file upload using a file reader. Here is the HTML code snippet I have: <md-progress-linear id="file-progress-indicator" md-mode="determinate" value="{{progress}}"></md-progress-linear> and below is m ...

Dropped down list failing to display JSON data

I created a website where users can easily update their wifi passwords. The important information is stored in the file data/data.json, which includes details like room number, AP name, and password. [ {"Room": "room 1", "AP nam ...

Dealing with functions that may not consistently return a promise

When dealing with a situation where a function does not always return a promise, how can it be best handled? The complexity of my current code prevents me from providing a detailed explanation, but essentially, the issue involves checking a condition and t ...

How can we access a value within a deeply nested JSON object in Node.js when the key values in between are not

In the nested configuration object provided below, I am seeking to retrieve the value associated with key1, which in this case is "value1". It's important to note that while key1 remains static, the values for randomGeneratedNumber and randomGenerated ...

Error: null does not have the property 'renderView' to be read

My goal is to set up a main page in React.js with two buttons: Option 1 and Option 2. Clicking on Option 1 should redirect the user to the Main1 page, while clicking on Option 2 should lead them to Main2. It seems straightforward, but I am encountering the ...