Skip to content

Commit 5a8a330

Browse files
feat: improve functions error messages (#4486)
* feat: implement better error pages for functions in CLI
1 parent 92d621b commit 5a8a330

File tree

4 files changed

+392
-9
lines changed

4 files changed

+392
-9
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
"Gergely Nemeth (https://twitter.com/nthgergo)",
4949
"HonkingGoose",
5050
"Ian Martorell <[email protected]>",
51-
"Ibrahima",
51+
"Ibrahima G. Coulibaly",
5252
"Jackie Macharia (wangoimacharia.dev)",
5353
"Jacob Schatz",
5454
"Jake Jarvis <[email protected]> (https://twitter.com/jakejarvis)",

src/lib/functions/server.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ const createHandler = function (options) {
161161
return
162162
}
163163

164-
handleSynchronousFunction(error, result, response)
164+
handleSynchronousFunction(error, result, request, response)
165165
}
166166
}
167167
}

src/lib/functions/synchronous.js

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// @ts-check
22
const { Buffer } = require('buffer')
3+
const { readFile } = require('fs').promises
4+
const { join } = require('path')
35

46
const { NETLIFYDEVERR } = require('../../utils')
57

@@ -15,15 +17,15 @@ const addHeaders = (headers, response) => {
1517
})
1618
}
1719

18-
const handleSynchronousFunction = function (err, result, response) {
20+
const handleSynchronousFunction = function (err, result, request, response) {
1921
if (err) {
20-
return handleErr(err, response)
22+
return handleErr(err, request, response)
2123
}
2224

2325
const { error } = validateLambdaResponse(result)
2426
if (error) {
2527
console.log(`${NETLIFYDEVERR} ${error}`)
26-
return handleErr(error, response)
28+
return handleErr(error, request, response)
2729
}
2830

2931
response.statusCode = result.statusCode
@@ -36,14 +38,36 @@ const handleSynchronousFunction = function (err, result, response) {
3638
response.end()
3739
}
3840

39-
const formatLambdaLocalError = (err) => `${err.errorType}: ${err.errorMessage}\n ${err.stackTrace.join('\n ')}`
41+
const formatLambdaLocalError = (err, acceptsHtml) =>
42+
acceptsHtml
43+
? JSON.stringify({
44+
errorType: err.errorType,
45+
errorMessage: err.errorMessage,
46+
trace: err.stackTrace,
47+
})
48+
: `${err.errorType}: ${err.errorMessage}\n ${err.stackTrace.join('\n ')}`
4049

41-
const handleErr = function (err, response) {
50+
let errorTemplateFile
51+
52+
const renderErrorTemplate = async (errString) => {
53+
const regexPattern = /<!--@ERROR-DETAILS-->/g
54+
errorTemplateFile = errorTemplateFile || (await readFile(join(__dirname, './templates/function-error.html'), 'utf-8'))
55+
56+
return errorTemplateFile.replace(regexPattern, errString)
57+
}
58+
59+
const processRenderedResponse = async (err, request) => {
60+
const acceptsHtml = request.headers && request.headers.accept && request.headers.accept.includes('text/html')
61+
const errorString = typeof err === 'string' ? err : formatLambdaLocalError(err, acceptsHtml)
62+
63+
return acceptsHtml ? await renderErrorTemplate(errorString) : errorString
64+
}
65+
66+
const handleErr = async (err, request, response) => {
4267
detectAwsSdkError({ err })
4368

4469
response.statusCode = 500
45-
const errorString = typeof err === 'string' ? err : formatLambdaLocalError(err)
46-
response.end(errorString)
70+
response.end(await processRenderedResponse(err, request))
4771
}
4872

4973
const validateLambdaResponse = (lambdaResponse) => {

0 commit comments

Comments
 (0)