vite icon indicating copy to clipboard operation
vite copied to clipboard

[Feature request] Show browser error overlay for runtime errors

Open martinszeltins opened this issue 3 years ago • 8 comments

I really like the browser error overlay that we get for compile errors (server.hmr.overlay). But runtime errors still appear only in console. It would be nice if runtime errors could also be displayed using the nice browser error overlay.

For example, it would be nice to get the overlay if I forgot to import ref:

<script setup>
    import HelloWorld from './components/HelloWorld.vue'

    const name = ref('Martin')
</script>

I'm talking about this overlay:

martinszeltins avatar Feb 18 '21 13:02 martinszeltins

Sometimes runtime errors occur after most of the page is loaded normally and the page can be used normally. In this case, will the page be replaced with the browser error overlay?

ygj6 avatar Mar 04 '21 07:03 ygj6

In React they prevent partial page from being rendered if there is an error, so error overlay is appropriate in all cases. It would be a nice enhancement particularly for new users and is present in CRA, NX, Snowpack etc.

jugglingcats avatar Apr 19 '21 14:04 jugglingcats

The overlay is an overlay so it's not replaced, it's overlaid or am I missing something here?

This does the trick for me:

// REGISTER ERROR OVERLAY
const showErrorOverlay = err => {
    // must be within function call because that's when the element is defined for sure.
    const ErrorOverlay = customElements.get('vite-error-overlay')
    // don't open outside vite environment
    if (!ErrorOverlay) {return}
    console.log(err)
    const overlay = new ErrorOverlay(err)
    document.body.appendChild(overlay)
}

window.addEventListener('error', showErrorOverlay)
window.addEventListener('unhandledrejection', ({reason}) => showErrorOverlay(reason))

janwirth avatar May 23 '21 12:05 janwirth

@FranzSkuffka Almost but the overlay needs the frame to be defined on the error to get correct formatting.

The code you posted will essentially show

Error: boom
    at http://localhost:3000/src/index.tsx:17:7

vs what I think most people expect

Runtime error at [filepath]
[error message]
/[filepath]:17:0
17 |      throw new Error('boom')
18 |      ^  

at [stacktrace]

On an unrelated note small bug in the code you posted, I think you meant to pass in the error not the event.

window.addEventListener('error', ({error}) => showErrorOverlay(error));

andrew-knack avatar Sep 03 '21 17:09 andrew-knack

Please prioritise this one, we are all spoilt by our previous experiences with webpack and other dev-servers. Really hard to live without the run-time overlay. Thanks!

TechAkayy avatar Dec 16 '21 15:12 TechAkayy

Thanks @arbassett for the related PR (#6274) you are working on. Will this PR cover showing all runtime errors in the overlay? Would be great if it does.

Here is example where prop validations fail (validator fn & type check). At the moment, we are forced to keep the browser console always open to even notice these important errors.

image

TechAkayy avatar Jan 25 '22 01:01 TechAkayy

I thought i was doing something wrong, but it really is a problem. I would really love to see this improved

Inviz avatar Jan 18 '23 06:01 Inviz

// REGISTER ERROR OVERLAY
const showErrorOverlay = err => {
    // must be within function call because that's when the element is defined for sure.
    const ErrorOverlay = customElements.get('vite-error-overlay')
    // don't open outside vite environment
    if (!ErrorOverlay) {return}
    console.log(err)
    const overlay = new ErrorOverlay(err)
    document.body.appendChild(overlay)
}

window.addEventListener('error', showErrorOverlay)
window.addEventListener('unhandledrejection', ({reason}) => showErrorOverlay(reason))

Fantastic, seems to have solved it for now.

uwaisdev avatar Jan 24 '23 07:01 uwaisdev

The overlay is an overlay so it's not replaced, it's overlaid or am I missing something here?

This does the trick for me:

// REGISTER ERROR OVERLAY
const showErrorOverlay = err => {
    // must be within function call because that's when the element is defined for sure.
    const ErrorOverlay = customElements.get('vite-error-overlay')
    // don't open outside vite environment
    if (!ErrorOverlay) {return}
    console.log(err)
    const overlay = new ErrorOverlay(err)
    document.body.appendChild(overlay)
}

window.addEventListener('error', showErrorOverlay)
window.addEventListener('unhandledrejection', ({reason}) => showErrorOverlay(reason))

I'm able to make the overlay more usable with information such as stacktrace using window.onerror and pass err object from 5th param. I also check if it's dev env to make sure it doesn't include this code in prod in case causing any side effect

if (import.meta.env.DEV) {
  window.onerror = (event, source, lineno, colno, err) => {
    // must be within function call because that's when the element is defined for sure.
    const ErrorOverlay = customElements.get('vite-error-overlay');
    // don't open outside vite environment
    if (!ErrorOverlay) {
      return;
    }
    const overlay = new ErrorOverlay(err);
    document.body.appendChild(overlay);
  };
}

Example using window.onerror

image

addEventListener('error', ...) only emit the error event which doesn't include stacktrace, see: https://developer.mozilla.org/en-US/docs/Web/API/Window/error_event#syntax

vKongv avatar Apr 08 '23 02:04 vKongv

Where do you precisely add this code @vKongv for it to work?

I've tried adding it in the index.tsx of a React app to make it work. It does work for errors in that file, but fails for any other file.

c10b10 avatar Aug 03 '23 13:08 c10b10

@c10b10 you can dump it into <script> tag in your index.html. However I am also wondering what's the best way to avoid bundling this code 🤔

krzkaczor avatar Aug 04 '23 07:08 krzkaczor

Not sure if there's a better way to do this at this point, but for ErrorEvents, you also need to pass the error property into ErrorOverlay:

window.addEventListener('error', ({error}) => showErrorOverlay(error)); // here

lxe avatar Oct 05 '23 16:10 lxe

A little hint for those who are using typescript and would like to switch the prop err from any to something more accurate reading their code from hmrPayload.ts, ref: https://github.com/vitejs/vite/blob/main/packages/vite/types/hmrPayload.d.ts#L45

import type { ErrorPayload } from 'vite'

export const showErrorOverlay = (err: Partial<ErrorPayload['err']>) => {
  const ErrorOverlay = customElements.get('vite-error-overlay')
  if (ErrorOverlay == null) return
  document.body.appendChild(new ErrorOverlay(err))
}

Walidoux avatar Nov 02 '23 02:11 Walidoux