You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Propagate framework errors to user application #686
Currently, errors that happen in the framework express layer are passed to the default express error handler. The default error handler returns the error to the client with a stack trace if in non-prod enviornments. It would be useful for certain cases for the user to have context of what happened during a request instead of the user being bypassed entirely. Instead, if the user has an error handler middleware installed in their application, we should pass the framework error to the user's error handler.
For example, if the framework gets a request with a bad json body.
// Post request with bad JSON
http.post("/", "{"id": "Hello}");
The framework responds with the following not very helpful message from the Express default error handler:
SyntaxError: Expected double-quoted property name in JSON at position 20 (line 3 column 1)
at JSON.parse (<anonymous>)
at parse (functions-framework-nodejs/node_modules/body-parser/lib/types/json.js:92:19)
at functions-framework-nodejs/node_modules/body-parser/lib/read.js:128:18
at AsyncResource.runInAsyncScope (node:async_hooks:211:14)
at invokeCallback (functions-framework-nodejs/node_modules/raw-body/index.js:238:16)
at done (functions-framework-nodejs/node_modules/raw-body/index.js:227:7)
at IncomingMessage.onEnd (functions-framework-nodejs/node_modules/raw-body/index.js:287:7)
at IncomingMessage.emit (node:events:518:28)
at endReadableNT (node:internal/streams/readable:1698:12)
at process.processTicksAndRejections (node:internal/process/task_queues:90:21)
There should be an option to propagate errors to the user client applcation, so their error handler is triggered and can preform logging, mitigations, or any other action the user wants instead of ignoring and leaving their application in the dust.
Facing the same issue : I need to handle json parsing errors in the way the specs I implement specify it.
Maybe, it would be easier just to have a way to deactivate the json parsing inside the framework and let the function code (express style) parse the body and handle potential errors.
Something like --disableMiddleware so in the server.js ligne 90, we can have :
Let me think more on this. In my case, if I pass an error handler to my application its only triggered through certain situtations but not all since the parent application installs its own error handler. Let me see if your solution works.
Adding a minimal repro in support of this, against 5.0.5.
index.js:
constfunctions=require("@google-cloud/functions-framework");constexpress=require("express");constapp=express();app.use(express.json());app.post("/",(req,res)=>res.json({ok: true,body: req.body}));// The application's own error handler. Never reached for a malformed body.app.use((err,req,res,next)=>{console.log("user error handler reached:",err.type);res.status(400).json({error: "handled by the application"});});functions.http("fn",app);
A valid body returns {"ok":true,"body":{"a":1}}, and the malformed one never logs user error handler reached.
Cause:build/src/server.js (5.0.5, lines 82-88) mounts bodyParser.json / text / urlencoded / raw ahead of the user function, with no error-handling middleware after them. body-parser's entity.parse.failed error therefore falls through to Express's default finalhandler. The function's own express.json() is a no-op (the body is already consumed and req._body is set), so nothing in the application can shape this response.
Why it matters: for a JSON API whose clients parse a JSON error envelope, the one error they can't parse is the malformed-request error, and there's no way to fix it from inside the function.
Either shape discussed here would solve it:
Forward the parse error to the user function (for example, leave req.body unset with req.rawBody available and the error attached), so the application's own error handling applies.
An opt-out of the built-in parsers for HTTP functions, as in the --disableMiddleware suggestion above.
Option 1 looks less disruptive for existing users of req.body / req.rawBody.
For anyone arriving from Firebase: the Firebase functions emulator (firebase-tools, lib/emulator/functionsEmulatorRuntime.js) mounts the same parsers the same way, so local emulation behaves identically (with a stack trace in the page when NODE_ENV isn't production).
Another data point on 5.0.5 (Node.js 24, Cloud Functions gen2). The HTML error page is only part of it. A malformed body is rejected before the function runs, so nothing in the function runs for that request:
Authentication. An unauthenticated request with a malformed body gets a 400 instead of a 401, so the response shows a request got past the auth layer that never ran.
Logging and metrics. No request-scoped log line and no metric are emitted. In Cloud Logging, the only trace is the framework's stack trace from body-parser, without the execution context the function would normally add.
Response contract. An API that publishes an error format (JSON:API, RFC 7807 problem details, …) can't meet it.
exports.handler=(req,res)=>{console.log('handler reached');// never printed for a malformed bodyres.json({ok: true});};
curl -si -H 'Content-Type: application/json' -d '{"data":' localhost:8080
# HTTP/1.1 400 Bad Request# Content-Type: text/html; charset=utf-8# <pre>Bad Request</pre> (NODE_ENV=production; otherwise the full stack trace)
+1 to the earlier suggestion of a switch that turns off the framework's body parsing (and leaves rawBody intact). Given the concern in #255 about exposing middleware, that seems the smallest API surface. It would solve this issue and also the application/*+json media types landing as a raw Buffer (see #232). The function would parse the body itself and own the error response. PR #685 would also work for us, as long as the error handler runs in the function's context (where auth and logging live).
Workaround we run in production, in case it helps others. It is fragile and depends on internals. The framework loads user code before it builds its express app, so the user module can replace the json export of the body-parser instance the framework resolves. application/json bodies then fall through to the raw parser, and the function parses req.body (a Buffer) itself:
const{ createRequire }=require('node:module');constframeworkRequire=createRequire(require.resolve('@google-cloud/functions-framework'));constbodyParser=frameworkRequire('body-parser');constjson=bodyParser.json;// The cloudevents parser passes an explicit `type` and is left alone.bodyParser.json=options=>json({ ...options,type: options.type??(()=>false)});
We pair it with a check that logs a warning if a JSON body ever arrives already parsed, so a framework upgrade that breaks the patch shows up. A supported option would let us remove all of this.
Activity
chatelgu commentedon Jun 25, 2025
Hi,
Facing the same issue : I need to handle json parsing errors in the way the specs I implement specify it.
Maybe, it would be easier just to have a way to deactivate the json parsing inside the framework and let the function code (express style) parse the body and handle potential errors.
Something like
--disableMiddlewareso in theserver.jsligne 90, we can have :Is it something that can suit you @gregorygaines ?
Question to @jihuin, waiting for a integration, is it possible to deploy a function with a custom
functions-framework-nodejs?gregorygaines commentedon Jun 25, 2025
Let me think more on this. In my case, if I pass an error handler to my application its only triggered through certain situtations but not all since the parent application installs its own error handler. Let me see if your solution works.
PeerLabs commentedon Sep 10, 2026
Adding a minimal repro in support of this, against 5.0.5.
index.js:A valid body returns
{"ok":true,"body":{"a":1}}, and the malformed one never logsuser error handler reached.Cause:
build/src/server.js(5.0.5, lines 82-88) mountsbodyParser.json/text/urlencoded/rawahead of the user function, with no error-handling middleware after them. body-parser'sentity.parse.failederror therefore falls through to Express's default finalhandler. The function's ownexpress.json()is a no-op (the body is already consumed andreq._bodyis set), so nothing in the application can shape this response.Why it matters: for a JSON API whose clients parse a JSON error envelope, the one error they can't parse is the malformed-request error, and there's no way to fix it from inside the function.
Either shape discussed here would solve it:
req.bodyunset withreq.rawBodyavailable and the error attached), so the application's own error handling applies.--disableMiddlewaresuggestion above.Option 1 looks less disruptive for existing users of
req.body/req.rawBody.For anyone arriving from Firebase: the Firebase functions emulator (
firebase-tools,lib/emulator/functionsEmulatorRuntime.js) mounts the same parsers the same way, so local emulation behaves identically (with a stack trace in the page whenNODE_ENVisn'tproduction).blackakula commentedon Oct 22, 2026
Another data point on 5.0.5 (Node.js 24, Cloud Functions gen2). The HTML error page is only part of it. A malformed body is rejected before the function runs, so nothing in the function runs for that request:
+1 to the earlier suggestion of a switch that turns off the framework's body parsing (and leaves
rawBodyintact). Given the concern in #255 about exposing middleware, that seems the smallest API surface. It would solve this issue and also theapplication/*+jsonmedia types landing as a rawBuffer(see #232). The function would parse the body itself and own the error response. PR #685 would also work for us, as long as the error handler runs in the function's context (where auth and logging live).Workaround we run in production, in case it helps others. It is fragile and depends on internals. The framework loads user code before it builds its express app, so the user module can replace the
jsonexport of thebody-parserinstance the framework resolves.application/jsonbodies then fall through to therawparser, and the function parsesreq.body(aBuffer) itself:We pair it with a check that logs a warning if a JSON body ever arrives already parsed, so a framework upgrade that breaks the patch shows up. A supported option would let us remove all of this.