Skip to content

Rendering component with errors causes process to crash #3075

@pmmmwh

Description

@pmmmwh

What versions are you using? (if relevant)

@react-email/render@2.0.4

Describe the Bug

Using Node.js, when rendering a component that crashes (e.g. with a TypeError), the error propagates upwards and crashes the whole process.

What is affected (leave empty if unsure)

Render Utility

Link to the code that reproduces this issue

index.ts

import Fastify from "fastify";
import { jsx } from "react/jsx-runtime";

import Template from "./Template.tsx";

const fastify = Fastify();

fastify.get(
  "/render",
  async (request, reply) => {
    try {
      // Intentionally missing a prop to trigger the error
      const html = await render(jsx(Template, {}));
      return await reply.send({ html });
    } catch (err) {
      // This catch block fails to catch the error!!
      request.log.error(err, "Failed to render");
      throw err;
    }
  },
);

try {
  await fastify.listen({
    host: "0.0.0.0",
    port: 3000,
  });
} catch (err) {
  fastify.log.error(err);
  process.exit(1);
}

template.tsx

import { Section, Text } from "@react-email/components";

export default function Template(props) {
  const { test } = props;

  return (
    <Section>
      {/* This line will trigger a `TypeError`, since `test` is not provided as a prop (= undefined) */}
      {test.a && (
        <Text>Test</Text>
      )}
    </Section>
  );
}

package.json

{
  "scripts": {
    "dev": "node --enable-source-maps --import @oxc-node/core/register --watch src/index.ts"
  },
  "dependencies": {
    "@react-email/components": "^1.0.9",
    "@react-email/render": "^2.0.4",
    "fastify": "^5.8.2",
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  },
  "devDependencies": {
    "@oxc-node/core": "^0.0.35",
    "@types/node": "^24.12.0",
    "@types/react": "^19.2.14",
    "@types/react-dom": "^19.2.3",
    "react-email": "^5.2.9",
    "typescript": "^5.9.3"
  }
}

To Reproduce

Run the server:

npm run dev

Then, hit the /render endpoint.

Expected Behavior

The error should not propagate to root and crash the whole server, and is caught by the catch block instead.

I suspect this is related to these two lines:

// Throw immediately when an error occurs to prevent CSR fallback
throw error;

From local patching and testing, it seems to work as expected if the throw call is swapped for a reject instead - but I do not know if that would cause other side effects.

What's your node version? (if relevant)

24.14.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions