diff --git a/services/filestore/app/js/FileController.js b/services/filestore/app/js/FileController.js index 1fe22f74bc..0ccb332516 100644 --- a/services/filestore/app/js/FileController.js +++ b/services/filestore/app/js/FileController.js @@ -68,7 +68,11 @@ function getFile(req, res, next) { } pipeline(fileStream, res, err => { - if (err && err.code === 'ERR_STREAM_PREMATURE_CLOSE') { + if ( + err && + (err.code === 'ERR_STREAM_PREMATURE_CLOSE' || + err.code === 'ERR_STREAM_UNABLE_TO_PIPE') + ) { res.end() } else if (err) { next( diff --git a/services/history-v1/api/controllers/projects.js b/services/history-v1/api/controllers/projects.js index 5d6eb5b5aa..ce75cb884b 100644 --- a/services/history-v1/api/controllers/projects.js +++ b/services/history-v1/api/controllers/projects.js @@ -373,7 +373,10 @@ async function getProjectBlob(req, res, next) { try { await pipeline(stream, res) } catch (err) { - if (err?.code === 'ERR_STREAM_PREMATURE_CLOSE') { + if ( + err?.code === 'ERR_STREAM_PREMATURE_CLOSE' || + err?.code === 'ERR_STREAM_UNABLE_TO_PIPE' + ) { res.end() } else { throw OError.tag(err, 'error transferring stream', { projectId, hash }) diff --git a/services/real-time/app.js b/services/real-time/app.js index d04a2c7aa6..c60a2202c3 100644 --- a/services/real-time/app.js +++ b/services/real-time/app.js @@ -291,6 +291,7 @@ if (Settings.shutdownDrainTimeWindow) { 'EPIPE', 'ECONNRESET', 'ERR_STREAM_WRITE_AFTER_END', + 'ERR_STREAM_UNABLE_TO_PIPE', ].includes(error.code) || // socket.io error handler sending on polling connection again. (error.code === 'ERR_HTTP_HEADERS_SENT' && diff --git a/services/web/app.mjs b/services/web/app.mjs index 9103dc3d4e..353f4a2541 100644 --- a/services/web/app.mjs +++ b/services/web/app.mjs @@ -44,9 +44,16 @@ if (Settings.catchErrors) { process.removeAllListeners('uncaughtException') process.removeAllListeners('unhandledRejection') process - .on('uncaughtException', error => + .on('uncaughtException', error => { + if (error.code === 'ERR_STREAM_UNABLE_TO_PIPE') { + metrics.inc('disconnected_write', 1, { status: error.code }) + return logger.warn( + { err: error }, + 'attempted to write to disconnected client' + ) + } logger.error({ err: error }, 'uncaughtException') - ) + }) .on('unhandledRejection', (reason, p) => { logger.error({ err: reason }, 'unhandledRejection at Promise', p) }) diff --git a/services/web/app/src/Features/Compile/ClsiCacheController.mjs b/services/web/app/src/Features/Compile/ClsiCacheController.mjs index fd789afdd1..e2dbfdaac3 100644 --- a/services/web/app/src/Features/Compile/ClsiCacheController.mjs +++ b/services/web/app/src/Features/Compile/ClsiCacheController.mjs @@ -86,7 +86,8 @@ async function downloadFromCache(req, res) { if ( streamingStarted && reqAborted && - err.code === 'ERR_STREAM_PREMATURE_CLOSE' + (err.code === 'ERR_STREAM_PREMATURE_CLOSE' || + err.code === 'ERR_STREAM_UNABLE_TO_PIPE') ) { // Ignore noisy spurious error return diff --git a/services/web/app/src/Features/Compile/CompileController.mjs b/services/web/app/src/Features/Compile/CompileController.mjs index 0da893013f..a518125257 100644 --- a/services/web/app/src/Features/Compile/CompileController.mjs +++ b/services/web/app/src/Features/Compile/CompileController.mjs @@ -596,7 +596,8 @@ const _CompileController = { if ( streamingStarted && reqAborted && - err.code === 'ERR_STREAM_PREMATURE_CLOSE' + (err.code === 'ERR_STREAM_PREMATURE_CLOSE' || + err.code === 'ERR_STREAM_UNABLE_TO_PIPE') ) { // Ignore noisy spurious error return diff --git a/services/web/app/src/Features/FileStore/FileStoreController.mjs b/services/web/app/src/Features/FileStore/FileStoreController.mjs index 0d1ea402d1..3433fa5dea 100644 --- a/services/web/app/src/Features/FileStore/FileStoreController.mjs +++ b/services/web/app/src/Features/FileStore/FileStoreController.mjs @@ -91,7 +91,8 @@ async function getFile(req, res) { if ( err instanceof Error && 'code' in err && - err.code === 'ERR_STREAM_PREMATURE_CLOSE' + (err.code === 'ERR_STREAM_PREMATURE_CLOSE' || + err.code === 'ERR_STREAM_UNABLE_TO_PIPE') ) { // Ignore clients closing the connection prematurely return diff --git a/services/web/app/src/infrastructure/ServeStaticWrapper.mjs b/services/web/app/src/infrastructure/ServeStaticWrapper.mjs index 1462b0c327..6f1fd4e6de 100644 --- a/services/web/app/src/infrastructure/ServeStaticWrapper.mjs +++ b/services/web/app/src/infrastructure/ServeStaticWrapper.mjs @@ -15,7 +15,10 @@ function serveStaticWrapper(root, options) { return next() } - if (error.code !== 'ERR_STREAM_PREMATURE_CLOSE') { + if ( + error.code !== 'ERR_STREAM_PREMATURE_CLOSE' && + error.code !== 'ERR_STREAM_UNABLE_TO_PIPE' + ) { return next(error) }