processWebhooks(): Failed to process webhook: Error: No body was received when processing webhook

I have a custom app that I started w/ the tutorial. I did not touch anything in the webhook handling code, it looks like this in web/index.js:

import webhookHandlers from "./webhook-handlers.js";
...

const app = express();
...
app.post(
  shopify.config.webhooks.path,
  // -ignore
  shopify.processWebhooks({ webhookHandlers: webhookHandlers })
);

I have not edit’d the webhook-handlers.js file either, it starts out like this:

export default {
  PRODUCTS_UPDATE: {
    deliveryMethod: DeliveryMethod.Http,
    callbackUrl: "/api/webhooks",
    callback: async (topic, shop, body, webhookId) => {
      console.log('--- Product update ---');
      const payload = JSON.parse(body);
      console.log(payload);
      console.log('--- /Product update ---');
    },
  },
...

I wanted to test this out, so I went to Admin Settings->Notifications and added Product Update webhook as follows:

And then I click on the ‘Send test notification’

dumbo82_1-1678992870348.png

In my app, it receives the notification, but the processWebhooks() gives me this error even though I do see a body:

2023-03-16 18:44:56 | backend  | [shopify-api/INFO] Processing webhook request | {apiVersion: , domain: , topic: , webhookId: }
2023-03-16 18:44:56 | backend  | [shopify-app/ERROR] Failed to process webhook: Error: No body was received when processing webhook

To debug, I log the full request to console and i did see it come back w/ a body portion:

2023-03-16 18:57:38 | backend | body: {> 2023-03-16 18:57:38 | backend | id: 788032119674292900,> 2023-03-16 18:57:38 | backend | title: ‘Example T-Shirt’,> 2023-03-16 18:57:38 | backend | body_html: ‘An example T-Shirt’,> 2023-03-16 18:57:38 | backend | vendor: ‘Acme’,> 2023-03-16 18:57:38 | backend | product_type: ‘Shirts’,> 2023-03-16 18:57:38 | backend | created_at: null,> 2023-03-16 18:57:38 | backend | handle: ‘example-t-shirt’,> 2023-03-16 18:57:38 | backend | updated_at: ‘2023-03-16T14:57:38-04:00’,> 2023-03-16 18:57:38 | backend | published_at: ‘2023-03-16T14:57:38-04:00’,> 2023-03-16 18:57:38 | backend | template_suffix: null,> 2023-03-16 18:57:38 | backend | status: ‘active’,> …> 2023-03-16 18:57:38 | backend | images: [ [Object] ],> 2023-03-16 18:57:38 | backend | image: null> 2023-03-16 18:57:38 | backend | },> 2023-03-16 18:57:38 | backend | _body: true,

Hey,

I figured it out.

Add the following to your main index.js

const bodyParserPrewiring = (server) => {
  // save a raw (unprocessed) version of 'body' to 'rawBody'
  function parseVerify(req, res, buf, encoding) {
    if (buf && buf.length) {
      req.rawBody = buf.toString(encoding || 'utf8')
    }
  }

  server.use(bodyParser.json({
    verify: parseVerify,
    limit: '10mb'
  }));

  server.use(bodyParser.urlencoded({
    extended: true,
    verify: parseVerify,
    limit: '10mb'
  }));
}

const app = express();
bodyParserPrewiring(app)
// for webhooks, convert the parsed body back to raw body
app.post("/api/webhooks", function(req, res, next) {
  req.body = req.rawBody
  next(); // go on to the real webhook handler
});

What’s happening, and I don’t know why, is req.body is being processed into JSON, the shopify webhook handler expects the original raw string and so it fails.

So the fix is, before anything else, save a raw copy of the body, and then before your webhook handler, swap out the JSON body with the raw body.

You need to make sure that this snippet:

app.post(
  shopify.config.webhooks.path,
  // -ignore
  shopify.processWebhooks({ webhookHandlers: webhookHandlers })
);

is before the expression.json() middleware:

app.use(express.json());

Like this:

const app = express();

app.post(
  shopify.config.webhooks.path,
  // -ignore
  shopify.processWebhooks({ webhookHandlers: webhookHandlers })
);

app.use(express.json());

That was it for me. Make sure to append

app.use(bodyParser.json());after the Shopify CLI code

thanks worked for me too, putting shopify.process before app.use(express.json())