next.js icon indicating copy to clipboard operation
next.js copied to clipboard

Thrown Error in Client Component is not triggering Error Boundary

Open seanmcquaid opened this issue 2 years ago • 5 comments

Verify canary release

  • [X] I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System: Platform: darwin Arch: x64 Version: Darwin Kernel Version 21.4.0: Mon Feb 21 20:35:58 PST 2022; root:xnu-8020.101.4~2/RELEASE_ARM64_T6000 Binaries: Node: 19.0.0 npm: 8.19.2 Yarn: 1.22.19 pnpm: 7.14.1 Relevant packages: next: 13.0.2 eslint-config-next: 13.0.2 react: 18.2.0 react-dom: 18.2.0

What browser are you using? (if relevant)

N/A

How are you deploying your application? (if relevant)

N/A

Describe the Bug

Throw an unhandled Error in a Client Component in Next 13. Notice that the Error is logged to the console but no Error Boundary is triggered even if a error.tsx file is present in the root directory.

Expected Behavior

I would expect that error.tsx would catch both Client Side and Server Side unhandled Errors.

Link to reproduction

https://github.com/seanmcquaid/next-13-bug-reproduction

To Reproduce

  • Run the app locally with next dev
  • Click one of the lines of text
  • Verify that the console has an unhandled Error logged but no Error Boundary has been triggered

seanmcquaid avatar Nov 06 '22 01:11 seanmcquaid

Facing the same issue

sreeisalso avatar Nov 06 '22 12:11 sreeisalso

The error is triggered in onClick in your example, this does not trigger error boundaries in React as per the documentation: https://reactjs.org/docs/error-boundaries.html#introducing-error-boundaries.

Maybe the beta docs (https://beta.nextjs.org/docs/routing/error-handling) can outline the cases where error boundaries don't catch.

timneutkens avatar Nov 06 '22 15:11 timneutkens

The error is triggered in onClick in your example, this does not trigger error boundaries in React as per the documentation: https://reactjs.org/docs/error-boundaries.html#introducing-error-boundaries.

Maybe the beta docs (https://beta.nextjs.org/docs/routing/error-handling) can outline the cases where error boundaries don't catch.

Totally valid! It wasn't clear to me based on the docs what the expected behavior should be (wasn't totally sure if these new error boundaries function any differently than the traditional error boundaries in React) so I appreciate your suggestion to outline those cases! Apologize for the issue being raised.

seanmcquaid avatar Nov 06 '22 17:11 seanmcquaid

Apologize for the issue being raised.

No need to apologize, this is great feedback for the docs 👍

timneutkens avatar Nov 07 '22 15:11 timneutkens

Facing the same issue on onClick event. Thanks for this answer.

FengeRVictor avatar Nov 12 '22 12:11 FengeRVictor

I have error.js in the same directory as page.jsx

and I have a server component like this

I don't see error.js doing anything here it's just failing, do I need to create the ErrorBoundary component ?? // Import your Client Component

import HomePage from './HomePage';
import Post from '../types/Post';

async function getPosts(): Promise<Post[]> {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts');
  return await res.json();
}

export default async function Page() {
  // Fetch data directly in a Server Component
  const recentPosts = await getPosts();
  // Forward fetched data to your Client Component
  return <HomePage recentPosts={recentPosts} />;
}

tkssharma avatar Feb 27 '23 05:02 tkssharma

I am facing the same issue in the onClick event. I thought the problem was due to the directory structure.

const handleSubmit = async (e) => {
    e.preventDefault()
    const { data, error } = await supabase.auth.signInWithPassword({
        email: "[email protected]",
        password: "sup3rs3cur3",
    });

    if (error) {
        throw new Error(error.message || "Unkown error")
    }
}

emrecoban avatar May 06 '23 21:05 emrecoban

Just in case someone is looking for this:

useState can be used to trigger the boundary error. Here is an example using the code above:

const [error, setError] = useState(false)

const handleSubmit = async (e) => {
    e.preventDefault()
    const { data, error } = await supabase.auth.signInWithPassword({
        email: "[email protected]",
        password: "sup3rs3cur3",
    });

    if (error) {
       setError(true)
    }
}

 if (error) {
    throw new Error('test')
  }

aaronjosephbrown avatar Jun 29 '23 02:06 aaronjosephbrown

Kalau-kalau ada yang mencari ini:

useState dapat digunakan untuk memicu kesalahan batas. Berikut adalah contoh menggunakan kode di atas:

const [kesalahan, setError] = useState(false)

const handleSubmit = async (e) => {
    e.preventDefault()
    const { data, error } = await supabase.auth.signInWithPassword({
        email: "[email protected]",
        password: "sup3rs3cur3",
    });

    if (error) {
       setError(true)
    }
}

 if (error) {
    throw new Error('test')
  }

it worked, thank you very much

mohamad-ridwan avatar Jul 05 '23 02:07 mohamad-ridwan

Alternatively when you have server actions enabled you can do something like this as startTransition from useTransition then binds the error to the component. Note that this is currently experimental but thought it would be good to point out.

"use client";

import { useTransition } from "react";

export default function MyComponent() {
  const [isPending, startTransition] = useTransition();

  const handleClick = () =>
    startTransition(() => {
      throw new Error("This failed");
    });

  return (
    <>
      <button onClick={handleClick}>Click me</button>
    </>
  );
}

next.config.js:

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    serverActions: true,
  },
};

module.exports = nextConfig;

timneutkens avatar Jul 05 '23 10:07 timneutkens

Just in case someone is looking for this:

useState can be used to trigger the boundary error. Here is an example using the code above:

const [error, setError] = useState(false)

const handleSubmit = async (e) => {
    e.preventDefault()
    const { data, error } = await supabase.auth.signInWithPassword({
        email: "[email protected]",
        password: "sup3rs3cur3",
    });

    if (error) {
       setError(true)
    }
}

 if (error) {
    throw new Error('test')
  }

Thanks, it helped much ;)

ozanyusufoglu avatar Sep 20 '23 05:09 ozanyusufoglu

The Nextjs docs should clearly document what can/cannot trigger the error.js component from rendering/displaying.

ECBSJ avatar Mar 10 '24 02:03 ECBSJ