#Running into some cryptic error. Help needed.

1 messages · Page 1 of 1 (latest)

burnt ingot
#

I am running into some error. This is on React 19, Nextjs 15 and all latest Convex. Has anyone seen this?

stray haven
#

Hmm might not even be cloudflare specific, I think the error message just came from a cloudflare worker that was doing ssr maybe

#

This has popped up in a few other places with different tooling. MessageChannel is a Node API used for SSR, so this error is happening in a non-node context. Another maybe related issue here that does involve Next 15: https://github.com/resend/react-email/issues/1630

burnt ingot
#

Thank you. Looking into all the links you shared now.

polar shore
#

interesting that you're getting the same error from next (presumably in a vercel environment) and from the convex environment. neither of them implement MessageChannel. any idea why you might be importing "react-dom/server"?

burnt ingot
#

Ah. Yes. That's interesting.

@stray haven , you saved the day. After much debugging, uninstalling and re-installing, react-email was indeed the culprit. Things worked once I commented out, and used pure html.

#

I initially tried jsx-email, but that had a bun of node things that made convex unhappy.

polar shore
#

hmm i think we want "react-email" to work. we'll look into it. can you share the exact version of react-email and react-dom and other packages that may be relevant (npm ls) 🙏

burnt ingot
#

Ah. It was not just react-email. Even after I removed react email, attempting to pass anything to the react prop of resend, triggered the same error. Just spent the last hour converting all to pure html with the help of claude. Then using the html prop instead with getSomeTemplate, which returns a html string. No errors. But If I pass the same html to the react prop, it shows the same error

#

I just updated all our packages. So the latest of all relevant package. The only react in the api folder is from resend and react-email. So its def something with react. Once I got rid of that, all works now

#

For example, the below does not work

stray haven
#

Sounds like react 19 specifically

burnt ingot
#

Yes

#

This works:

#

@stray haven Yes. React 19.

thick flower
#

Hi! I just ran into this exact issue tonight while trying to install and use react-email. Was there a solution identified?

#
"react": "^19.0.0",
"react-dom": "^19.0.0",
"@react-email/components": "0.0.32",
stray haven
#

Yeah, not using react. There’s a non-working and working example above

thick flower
#

RIP

#

I love the simplicity of Convex Auth but might need to switch to Clerk

split dagger
#

Just want to flag that we're having the same issue here, going for pure html for now, but would love to get updates if React 19 works at some point

glass river
#

Thanks for flagging, how would you describe the issue @split dagger, "React emails don't work with React 19 in Convex?" Sounds like it's to do with some Node.js specific APIs?

#

Sounds like we need to prioritize this, but I don't know what the issue is yet. If it's a general runtime API we can add it, but if the issue is that React Email now only supports Node.js for React 19 that's something we need to open an issue about

split dagger
stray haven
#

So two issues and solutions:

  1. MessageChannel not supported: use a node action.
  2. reactDOMServer.default.renderToPipeableStream is undefined: Add @react-email/components (or /render, whichever you import render from) to node.externalPackages in convex.json
stray haven
#

So the status is "React emails work with React 19 in Convex, but only for Node actions".

#

It is possible to use the Convex runtime, but the @react-email/render browser module is attempting to run reactDOMServer.renderToReadableStream when the actual import shape is reactDOMServer.default.renderToReadableStream. Works when patched. Going to see if there's an elegant solution, otherwise might make a patch-package for this.

stray haven
#

Here's the patch steps for anyone that wants this working in Convex runtime (patch below):

  • Make sure you're using @react-email/render 1.0.5 (or @react-email/components 0.0.35, which exports render from the same version)
  • Add the file above to a patches/ directory alongside your package.json (repo or project root)
  • Set up patch package to apply: https://www.npmjs.com/package/patch-package
#

/patches/@react-email+render+1.0.5.patch

diff --git a/node_modules/@react-email/render/dist/browser/index.mjs b/node_modules/@react-email/render/dist/browser/index.mjs
index 0d63ab6..74e9b0d 100644
--- a/node_modules/@react-email/render/dist/browser/index.mjs
+++ b/node_modules/@react-email/render/dist/browser/index.mjs
@@ -155,9 +155,9 @@ var render = (element, options) => __async(void 0, null, function* () {
   const suspendedElement = /* @__PURE__ */ jsx(Suspense, { children: element });
   const reactDOMServer = yield import("react-dom/server");
   let html2;
-  if (Object.hasOwn(reactDOMServer, "renderToReadableStream")) {
+  if (Object.hasOwn(reactDOMServer.default, "renderToReadableStream")) {
     html2 = yield readStream(
-      yield reactDOMServer.renderToReadableStream(suspendedElement)
+      yield reactDOMServer.default.renderToReadableStream(suspendedElement)
     );
   } else {
     yield new Promise((resolve, reject) => {
split dagger
#

@paper hatch

stray haven
#

Forgot to add, in Convex runtime I think you still need to polyfill MessageChannel, just put the MessageChannel mock below in a file and import it first in whatever file your email rendering is happening in. You may be able to get away with a more minimal polyfill but this one works.

// polyfill MessageChannel without using node:events
if (typeof MessageChannel === "undefined") {
  class MockMessagePort {
    onmessage: ((ev: MessageEvent) => void) | undefined;
    onmessageerror: ((ev: MessageEvent) => void) | undefined;

    close() {}
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    postMessage(_message: unknown, _transfer: Transferable[] = []) {}
    start() {}
    addEventListener() {}
    removeEventListener() {}
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    dispatchEvent(_event: Event): boolean {
      return false;
    }
  }

  class MockMessageChannel {
    port1: MockMessagePort;
    port2: MockMessagePort;

    constructor() {
      this.port1 = new MockMessagePort();
      this.port2 = new MockMessagePort();
    }
  }

  globalThis.MessageChannel =
    MockMessageChannel as unknown as typeof MessageChannel;
}
oblique glen
#

After doing some more reading - is there a recommended way to use @react-email/components with resend + convex-auth? Would love to get that set up in my new app

#

I was using the convex auth example repo - but it didn't have anything about this issue 😕

#

Just saw your response today about a PR for patching it 🙂 I'll keep my eyes peeled for that and save that work for later 👍

stray haven
#

Yeah it's complicated. There's an effort to provide an edge-light distro that would remove the need for a polyfill: https://github.com/resend/react-email/pull/2222

The default export issue has a PR open to but I'm having trouble finding it. At any rate, if you want to get this working I'd pin to 1.0.5 for now and use the fixes above. Otherwise hopefully fixes get in place soon.

oblique glen
#

Thanks for the context! We probably won’t go live with the product for another 6 weeks so I’ll wait to see if it gets fixed 😀😀

warped shuttle
stray haven
#

For anyone that's still seeing the MessageChannel undefined issue after adding the polyfill: the polyfill must be imported before the other imports. The polyfill can't be inlined above the imports, it will still execute after the imports.

livid jasper
#

I ran that patch and I'm getting this error

#

```Hit error while running auth:signIn:
Error: [Request ID: e2fcebe8dac81e7d] Server Error
Uncaught TypeError: reactDOMServer.renderToPipeableStream is not a function
at __spreadValues2.selectors (../../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@react-email/render/dist/browser/index.mjs:164:21)
at new Promise (<anonymous>)
at <anonymous> (../../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@react-email/render/dist/browser/index.mjs:163:6)
at next [as next] (<anonymous>)
at fulfilled (../../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@react-email/render/dist/browser/index.mjs:24:18)

at new Promise (<anonymous>)
at next [as next] (<anonymous>)
at async proxyAuthActionToConvex (../../../src/nextjs/server/proxy.ts:72:15)
at async (../../../src/nextjs/server/index.tsx:201:13) {

}```

#

@stray haven

stray haven
#

Ah, I don't think patch-package works with pnpm

#

I haven't used it, but if you follow their patching instructions you can try manually using the patch I shared above to make the changes.

livid jasper
#

I tried to remove pnpm from the project. and for some reason it's still trying to use the pnpm package

stray haven
#

If you want to drop pnpm, deleting node_modules and pnpm-lock.yaml should do it

livid jasper
#

I removed every reference of pnpm from the project and did a completely fresh npm install and it is still using pnpm for that function

#

Convex runtime wasn't running 🤦‍♂️

stray haven
#

ah that'll do it

#

working now?

thick flower
#

Following up here since I just ran into the same issue with Better Auth, Resend, React Email, and Convex (MessageChannel is not defined). This is what fixed it for me:

  1. Add convex.json at the root and specify @react-email/render as an external package:
{
  "node": {
    "externalPackages": ["@react-email/render"]
  }
}
  1. Add an override in package.json for @react-email/render. The latest version has fixed the renderToPipeableStream issue described above, however, the latest versions of react-email and @react-email/components don't yet rely on up-to-date @react-email/render... so you have to override it manually:
  "pnpm": {
    "overrides": {
      "@react-email/render": "1.1.2"
    }
  }
  1. Add the MessageChannel polyfill as described by @stray haven here: https://github.com/resend/react-email/issues/1630#issuecomment-2773421899 (I created a polyfills.ts file within convex/ and then added import "./pollyfills" to the top of convex/auth.ts

I think that's it! Hopefully we can remove the polyfill and override at some point in the future, but at least no package patch is required now.

GitHub

Describe the Bug Using React 19 + Next.js 15 I want to use @react-email/render on edge runtime. However, I got this error: unhandledRejection: Error: A Node.js API is used (MessageChannel) which is...

quaint solar
stray haven
stray haven
#

Update: only the polyfill is needed if you're on the latest version of the @react-email/* libs (step 3 from Eva's last comment), no convex.json or dependency overrides required. The polyfill will unfortunately be required indefinitely, the fix is currently at a standstill: https://github.com/resend/react-email/pull/2225

sharp fox
#

Thank you so much for the fix, I was trying to debug it for hours...
It works now!

urban fable
#

Hi everyone. Im in need of help. I have inserted this code ```if (typeof MessageChannel === "undefined") {
class MockMessagePort {
onmessage: ((ev: MessageEvent) => void) | undefined;
onmessageerror: ((ev: MessageEvent) => void) | undefined;

close() {}
postMessage(_message: unknown, _transfer: Transferable[] = []) {}
start() {}
addEventListener() {}
removeEventListener() {}
dispatchEvent(_event: Event): boolean {
  return false;
}

}

class MockMessageChannel {
port1: MockMessagePort;
port2: MockMessagePort;

constructor() {
  this.port1 = new MockMessagePort();
  this.port2 = new MockMessagePort();
}

}

globalThis.MessageChannel =
MockMessageChannel as unknown as typeof MessageChannel;
}
in the polyfills.ts last week and then I imported polyfills.ts in convex/auth.ts. It was working well until today. I got an error in convex logs sayingUncaught TypeError: reactDOMServer.renderToPipeableStream is not a function
at new Promise (<anonymous>)
at next [as next] (<anonymous>)``` . Anyone has any idea on how to fix this?

stray haven
urban fable
#

Thank you

little marlin
#

Just ran into this issue and my workaround was as shown in this picture, I am use 'use node' directive and then I replaced internalMutation to internalAction, have all the latest packages

stray haven
# warped rampart

Wherever you're sending the email from, the polyfill isn't getting imported

warped rampart
#

Is this not enought?

#

This part of being unable to setup a basic auth with otp is getting frustating

#

@stray haven any ideias?

#

I can upload my code to github is that helps

stray haven
heavy night
stray haven
#

ah hmm maybe spoke too soon

#

Convex no longer complains during deployment, but actually sending an email is still hitting this. Going to dig a bit.

heavy night
stray haven
#

That PR specifically provides alternative exports for Vercel (edge-light) and Cloudflare (workerd). Here's a support grid showing MessageChannel isn't supported in these runtimes: https://runtime-compat.unjs.io/#MessageChannel

Convex runtime uses the browser export, as these runtimes also would have prior to the new exports being added.

So maybe at some point an export for Convex runtime could be added. For now, the polyfill continues to be required.

stray haven
#

The polyfill should no longer be necessary in the Convex runtime as of @react-email/render 1.2.3.