From 385caa0d32ea9459d42caa4743f7841c7983fba9 Mon Sep 17 00:00:00 2001 From: Pablo Moreno Date: Wed, 30 Sep 2026 08:42:29 +0200 Subject: [PATCH] detect error caused by missing developer console config file --- src/RuntimeBaseCommand.js | 14 +++++++++++++- test/RuntimeBaseCommand.test.js | 26 ++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/RuntimeBaseCommand.js b/src/RuntimeBaseCommand.js index 70189ebd..ab8f8d03 100644 --- a/src/RuntimeBaseCommand.js +++ b/src/RuntimeBaseCommand.js @@ -96,7 +96,19 @@ class RuntimeBaseCommand extends Command { if (err) { let pretty = err.message || '' - if (err.name === 'OpenWhiskError') { + const connectionErrors = [err, err.error, err.cause] + const isConnectionReset = connectionErrors.some(error => { + if (!error) return false + return error.code === 'ECONNRESET' || + /ECONNRESET/i.test(error.message || '') || + /socket hang up/i.test(error.message || '') || + /(ECONNRESET|socket hang up)/i.test(typeof error.error === 'string' ? error.error : '') + }) + + if (isConnectionReset) { + pretty = 'the connection to the Runtime API was interrupted (socket hang up / ECONNRESET). ' + + 'Please try again in a few moments. Before you do, run `aio app use` to get the latest Adobe Developer Console configuration file.' + } else if (err.name === 'OpenWhiskError') { if (err.error && err.error.error) { pretty = err.error.error.toLowerCase() if (err.statusCode) pretty = `${pretty} (${getStatusCode(err.statusCode)})` diff --git a/test/RuntimeBaseCommand.test.js b/test/RuntimeBaseCommand.test.js index af2b2a54..8f3d882e 100644 --- a/test/RuntimeBaseCommand.test.js +++ b/test/RuntimeBaseCommand.test.js @@ -302,6 +302,32 @@ describe('instance methods', () => { expect(command.error).toHaveBeenCalledWith('msg: an error' + suffix) }) + test('connection reset gives actionable Runtime API guidance', async () => { + command.error = jest.fn() + const cause = Object.assign(new Error('read ECONNRESET'), { code: 'ECONNRESET' }) + const err = new OpenWhiskError('Unknown Error From API: read ECONNRESET', cause) + + await command.handleError('failed to list the activations', err) + + expect(command.error).toHaveBeenCalledWith( + 'failed to list the activations: the connection to the Runtime API was interrupted (socket hang up / ECONNRESET). ' + + 'Please try again in a few moments. Before you do, run `aio app use` to get the latest Adobe Developer Console configuration file.' + + suffix + ) + }) + + test('socket hang up gives actionable Runtime API guidance', async () => { + command.error = jest.fn() + + await command.handleError('failed to list the activations', new Error('socket hang up')) + + expect(command.error).toHaveBeenCalledWith( + 'failed to list the activations: the connection to the Runtime API was interrupted (socket hang up / ECONNRESET). ' + + 'Please try again in a few moments. Before you do, run `aio app use` to get the latest Adobe Developer Console configuration file.' + + suffix + ) + }) + test('openwhisk error, with internal error', async () => { command.error = jest.fn() const err = new Error('is')