[cli][node][node-bridge] improve edge/serverless function error messages (#9410)

The error messages shown during `vc dev` when an Edge or Serverless functions returns a promise that ends up being rejected could be better.

Main changes:

- removed "socket hang up" error messages because they were not helpful to the user
- changed serverless function error handling to log explicitly and exit
- changed serverless function error message to include the request path
- changed edge function error message to include request path and a faked (but useful) stack trace

## Current

### In Production

**Serverless Function:** In production, for a serverless function rejected promise, you'll see this in the logs:

```
Unhandled Promise Rejection 	{
  "errorType": "Runtime.UnhandledPromiseRejection",
  "errorMessage": "Error: intentional break!",
  "reason": {
    "errorType": "Error",
    "errorMessage": "intentional break!",
    "stack": [
      "Error: intentional break!",
      "    at handler (/var/task/api/node.js:3:9)",
      "    at Server.<anonymous> (/var/task/___vc/__helpers.js:813:19)",
      "    at Server.emit (node:events:527:28)",
      "    at parserOnIncoming (node:_http_server:956:12)",
      "    at HTTPParser.parserOnHeadersComplete (node:_http_common:128:17)"
    ]
  },
  "promise": {},
  "stack": [
    "Runtime.UnhandledPromiseRejection: Error: intentional break!",
    "    at process.<anonymous> (file:///var/runtime/index.mjs:1194:17)",
    "    at process.emit (node:events:539:35)",
    "    at process.emit (/var/task/___vc/__sourcemap_support.js:559:21)",
    "    at emit (node:internal/process/promises:140:20)",
    "    at processPromiseRejections (node:internal/process/promises:274:27)",
    "    at processTicksAndRejections (node:internal/process/task_queues:97:32)"
  ]
}
Unknown application error occurred
Runtime.Unknown
```

**Edge Function:** In production, for an edge function rejected promise, you'll see this in the logs:

```
Error: intentional break!
    at (api/edge.js:10:10)
```

In both cases, in the browser, you see the "This Serverless/Edge Function has crashed." template with no error message or stack trace.


### In `vc dev`


**Serverless Function:** In `vc dev`, for a serverless function rejected promise, you'll see this in the output:

```
Unhandled rejection: Error: intentional break!
    at handler (/Users/smassa/source/demo/edge-errors/api/node.js:3:9)
    at Server.<anonymous> (/Users/smassa/source/vercel/vercel/packages/node-bridge/helpers.js:813:19)
    at Server.emit (node:events:513:28)
    at Server.emit (node:domain:489:12)
    at parserOnIncoming (node:_http_server:998:12)
    at HTTPParser.parserOnHeadersComplete (node:_http_common:128:17)
Error: Failed to complete request to /api/node: Error: socket hang up
```

**Edge Function:** In `vc dev`, for an edge function rejected promise, you'll see this in the output:

```
Unhandled rejection: intentional break!
Error: Failed to complete request to /api/edge: Error: socket hang up
```

## After Changes

### In `vc dev`


**Serverless Function:** In `vc dev`, for a serverless function rejected promise, you'll see this in the output:

```
Rejected Promise returned from /api/node: Error: intentional break!
    at handler (/Users/smassa/source/demo/edge-errors/api/node.js:3:9)
    at Server.<anonymous> (/Users/smassa/source/vercel/vercel/packages/node-bridge/helpers.js:824:19)
    at Server.emit (node:events:513:28)
    at Server.emit (node:domain:489:12)
    at parserOnIncoming (node:_http_server:998:12)
    at HTTPParser.parserOnHeadersComplete (node:_http_common:128:17)
```

**Edge Function:** In `vc dev`, for an edge function rejected promise, you'll see this in the output:

```
Rejected Promise returned from api/edge: intentional break!
    at (api/edge.ts)
```

We can't show the real stack trace for Edge Functions because the bundling + VM execution mangles it. What's rendered here is a fake one, but it's still useful to the user.

If we currently showed the real stack trace for edge functions, it would look like:

```
Rejected Promise returned from api/edge: intentional break!
    at edge (evalmachine.<anonymous>:35:9)
    at FetchEvent.<anonymous> (evalmachine.<anonymous>:87:26)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async EdgeRuntime.dispatchFetch (evalmachine.<anonymous>:29:7)
    at async Server.handler (/Users/smassa/source/vercel/vercel/node_modules/.pnpm/edge-runtime@2.0.0/node_modules/edge-runtime/src/server/create-handler.ts:46:26)
```

## Follow Up

We'll look into improving the Edge Function error stack traces later.
This commit is contained in:
Sean Massa
2023-02-10 18:14:58 -06:00
committed by GitHub
parent 084125d90f
commit d628880942
4 changed files with 44 additions and 43 deletions

View File

@@ -2307,7 +2307,10 @@ function proxyPass(
res,
{ target: dest, ignorePath },
(error: NodeJS.ErrnoException) => {
devServer.output.error(
// only debug output this error because it's always something generic like
// "Error: socket hang up"
// and the original error should have already been logged
devServer.output.debug(
`Failed to complete request to ${req.url}: ${error}`
);
if (!res.headersSent) {