react-email
react-email copied to clipboard
`TypeError: dispatcher.getOwner is not a function` thrown when rendering an email template with React 19 RC
Describe the Bug
The following error is thrown when rendering an email template in a containerized Next.js 15 application using React 19.0.0-rc.
TypeError: dispatcher.getOwner is not a function
pangolin | at getOwner (/app/node_modules/react/cjs/react-jsx-runtime.development.js:349:54)
pangolin | at jsxDEVImpl (/app/node_modules/react/cjs/react-jsx-runtime.development.js:523:57)
pangolin | at process.env.NODE_ENV.exports.jsx (/app/node_modules/react/cjs/react-jsx-runtime.development.js:651:14)
pangolin | at Html (file:///app/node_modules/@react-email/html/dist/index.mjs:39:28)
pangolin | at renderWithHooks (/app/node_modules/react-dom/cjs/react-dom-server.node.production.js:4086:18)
pangolin | at renderElement (/app/node_modules/react-dom/cjs/react-dom-server.node.production.js:4482:18)
pangolin | at retryNode (/app/node_modules/react-dom/cjs/react-dom-server.node.production.js:4768:16)
pangolin | at renderNodeDestructive (/app/node_modules/react-dom/cjs/react-dom-server.node.production.js:4586:7)
pangolin | at renderNode (/app/node_modules/react-dom/cjs/react-dom-server.node.production.js:5025:14)
pangolin | at renderElement (/app/node_modules/react-dom/cjs/react-dom-server.node.production.js:4420:18)
Interestingly rendering works completely free of errors when running a dev server. I am using the following packages and versions.
{
"dependencies": {
"@hookform/resolvers": "3.9.0",
"@node-rs/argon2": "1.8.3",
"@oslojs/crypto": "1.0.1",
"@oslojs/encoding": "1.1.0",
"@radix-ui/react-avatar": "1.1.1",
"@radix-ui/react-checkbox": "1.1.2",
"@radix-ui/react-dialog": "1.1.2",
"@radix-ui/react-dropdown-menu": "2.1.2",
"@radix-ui/react-icons": "1.3.0",
"@radix-ui/react-label": "2.1.0",
"@radix-ui/react-popover": "1.1.2",
"@radix-ui/react-radio-group": "1.2.1",
"@radix-ui/react-select": "2.1.2",
"@radix-ui/react-separator": "1.1.0",
"@radix-ui/react-slot": "1.1.0",
"@radix-ui/react-switch": "1.1.1",
"@radix-ui/react-tabs": "1.1.1",
"@radix-ui/react-toast": "1.2.2",
"@react-email/components": "0.0.28",
"@react-email/tailwind": "1.0.2",
"@tanstack/react-table": "8.20.5",
"axios": "1.7.7",
"better-sqlite3": "11.3.0",
"class-variance-authority": "0.7.0",
"clsx": "2.1.1",
"cmdk": "1.0.0",
"cookie-parser": "1.4.6",
"cors": "2.8.5",
"drizzle-orm": "0.33.0",
"emblor": "1.4.6",
"eslint": "9.15.0",
"eslint-config-next": "15.0.3",
"express": "4.21.0",
"express-rate-limit": "7.4.0",
"glob": "11.0.0",
"helmet": "7.1.0",
"http-errors": "2.0.0",
"input-otp": "1.2.4",
"js-yaml": "4.1.0",
"lucide-react": "0.447.0",
"moment": "2.30.1",
"next": "15.0.1",
"next-themes": "0.3.0",
"node-fetch": "3.3.2",
"nodemailer": "6.9.15",
"oslo": "1.2.1",
"react": "19.0.0-rc.1",
"react-dom": "19.0.0-rc.1",
"react-hook-form": "7.53.0",
"rebuild": "0.1.2",
"tailwind-merge": "2.5.3",
"tailwindcss-animate": "1.0.7",
"vaul": "1.1.1",
"winston": "3.14.2",
"winston-daily-rotate-file": "5.0.0",
"ws": "8.18.0",
"zod": "3.23.8",
"zod-validation-error": "3.4.0"
},
"devDependencies": {
"react-email": "3.0.2",
"@dotenvx/dotenvx": "1.14.2",
"@esbuild-plugins/tsconfig-paths": "0.1.2",
"@types/better-sqlite3": "7.6.11",
"@types/cookie-parser": "1.4.7",
"@types/cors": "2.8.17",
"@types/express": "5.0.0",
"@types/js-yaml": "4.0.9",
"@types/node": "^20",
"@types/nodemailer": "6.4.16",
"@types/react": "npm:[email protected]",
"@types/react-dom": "npm:[email protected]",
"@types/ws": "8.5.13",
"@types/yargs": "17.0.33",
"drizzle-kit": "0.24.2",
"esbuild": "0.20.1",
"esbuild-node-externals": "1.13.0",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"tsc-alias": "1.8.10",
"tsx": "4.19.1",
"typescript": "^5",
"yargs": "17.7.2"
},
"overrides": {
"@types/react": "npm:[email protected]",
"@types/react-dom": "npm:[email protected]"
}
}
Which package is affected (leave empty if unsure)
No response
Link to the code that reproduces this issue
none
To Reproduce
Calling render from causes the error. The second log statement is never executed in the below example.
import { render } from "@react-email/render";
import { ReactElement } from "react";
logger.debug("Rendering email templatee...")
const emailHtml = await render(template);
logger.debug("Done rendering email templatee")
I also tried:
import { render } from "@react-email/components";
Expected Behavior
I expect the render function to produce the rendered HTML code without throwing an error.
What's your node version? (if relevant)
20.10.0
By tracing the error I noticed this has to do with NODE_ENV being set to production. This makes since as it worked for me in dev mode, but not in a production build. The following files are key:
node_modules/react/jsx-runtime.js
'use strict';
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-jsx-runtime.production.js');
} else {
module.exports = require('./cjs/react-jsx-runtime.development.js');
}
node_modules/react/cjs/react-jsx-runtime.production.js
"use strict";
var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"),
REACT_FRAGMENT_TYPE = Symbol.for("react.fragment");
function jsxProd(type, config, maybeKey) {
var key = null;
void 0 !== maybeKey && (key = "" + maybeKey);
void 0 !== config.key && (key = "" + config.key);
if ("key" in config) {
maybeKey = {};
for (var propName in config)
"key" !== propName && (maybeKey[propName] = config[propName]);
} else maybeKey = config;
config = maybeKey.ref;
return {
$$typeof: REACT_ELEMENT_TYPE,
type: type,
key: key,
ref: void 0 !== config ? config : null,
props: maybeKey
};
}
exports.Fragment = REACT_FRAGMENT_TYPE;
exports.jsx = jsxProd;
exports.jsxs = jsxProd;
node_modules/react/cjs/react-jsx-runtime.development.js
...
return describeUnknownElementTypeFrameInDEV(type(prototype));
} catch (x) {}
}
return "";
}
function getOwner() {
var dispatcher = ReactSharedInternals.A;
return null === dispatcher ? null : dispatcher.getOwner();
}
function hasValidKey(config) {
if (hasOwnProperty.call(config, "key")) {
var getter = Object.getOwnPropertyDescriptor(config, "key").get;
if (getter && getter.isReactWarning) return !1;
}
return void 0 !== config.key;
}
...
Notice how the production version does not have getOwner while the development version does. Setting NODE_ENV to development fixed the issue for me and I am able to use the render function as expected.
This leaves me to question whether I configuring something incorrectly or if this is a real bug. Please let me know.
This seems like an oddly specific issue, we'll need a minimal reproduction for it. Can you make one?
I am having the same problem, does anyone have a solution?
I also have this issue. Can't really find anything online...
The same issue
https://github.com/remix-run/react-router/issues/12138 provides a fix
I'm not using react-email but I had same issues with react-router. In my case in such as issue I had to use NODE_ENV=production or use production build because I used two react apps with different builds.
Closing as not planned, assuming the issue is not present anymore. If anyone has this problem again, make a minimal reproduction and I'll reopen
It is happening for me.
Here is a v0 repro: https://v0.dev/chat/fork-of-wysiwyg-email-editor-zJ6bz6PKqjY
Click on Export HTML button to see the error.
@rajat1saxena can't use that, too big to work with. Make a minimal one.
But just looking at it from the surface, it might be that some invalid type was passed to the JSX factory
@gabrielmfern here's a smaller v0 example: https://v0.dev/chat/react-email-error-getowner-TK7taTkIs98
and the v0 logs:
17:48:15.888Z [SERVER] Error rendering email: h.getOwner is not a function. (In 'h.getOwner()', 'h.getOwner' is undefined) 17:48:15.889Z [SERVER] Unhandled promise rejection: TypeError: ReadableByteStreamController is not implemented
By tracing the error I noticed this has to do with
NODE_ENVbeing set toproduction. This makes since as it worked for me in dev mode, but not in a production build. The following files are key:node_modules/react/jsx-runtime.js
'use strict';
if (process.env.NODE_ENV === 'production') { module.exports = require('./cjs/react-jsx-runtime.production.js'); } else { module.exports = require('./cjs/react-jsx-runtime.development.js'); } node_modules/react/cjs/react-jsx-runtime.production.js
"use strict"; var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); function jsxProd(type, config, maybeKey) { var key = null; void 0 !== maybeKey && (key = "" + maybeKey); void 0 !== config.key && (key = "" + config.key); if ("key" in config) { maybeKey = {}; for (var propName in config) "key" !== propName && (maybeKey[propName] = config[propName]); } else maybeKey = config; config = maybeKey.ref; return { $$typeof: REACT_ELEMENT_TYPE, type: type, key: key, ref: void 0 !== config ? config : null, props: maybeKey }; } exports.Fragment = REACT_FRAGMENT_TYPE; exports.jsx = jsxProd; exports.jsxs = jsxProd; node_modules/react/cjs/react-jsx-runtime.development.js
... return describeUnknownElementTypeFrameInDEV(type(prototype)); } catch (x) {} } return ""; } function getOwner() { var dispatcher = ReactSharedInternals.A; return null === dispatcher ? null : dispatcher.getOwner(); } function hasValidKey(config) { if (hasOwnProperty.call(config, "key")) { var getter = Object.getOwnPropertyDescriptor(config, "key").get; if (getter && getter.isReactWarning) return !1; } return void 0 !== config.key; } ... Notice how the production version does not have
getOwnerwhile the development version does. SettingNODE_ENVtodevelopmentfixed the issue for me and I am able to use the render function as expected.This leaves me to question whether I configuring something incorrectly or if this is a real bug. Please let me know.
This was the exact reason in my case. react use NODE_ENV as the env variable name in react package, I was also using NODE_ENV as the env name to keep my application's environment. Both conflicted in the production. Could resolve it by changing my application's NODE_ENV to another name(ex: APP_ENV) my application.