node-imap
node-imap copied to clipboard
Ending the connection results in random floating socket errors
I'm trying to close a no longer needed connection, and sometimes this leads to different socket errors.
const imap = new IMAP(config);
imap.once("close", (failed: boolean) => {
console.log(`closed, failed: ${failed}`);
});
imap.once("error", (e: Error) => {
console.log(e);
});
imap.once("ready", () => {
imap.end();
});
imap.connect();

Stack
anonymous(), MailboxUtilityTest.ts:32
onceWrapper(), events.js:291
emit(), events.js:203
_onError(), Connection.js:151
emit(), events.js:203
TLSSocket._emitTLSError(), _tls_wrap.js:748
onerror(), _tls_wrap.js:330
Async call from TLSWRAP
init(), inspector_async_hook.js:21
emitInitNative(), async_hooks.js:134
TLSSocket._wrapHandle(), _tls_wrap.js:514
TLSSocket(), _tls_wrap.js:412
connect(), _tls_wrap.js:1405
anonymous(), Connection.js:1708
Object.<anonymous>.Connection._resTagged(), Connection.js:1535
anonymous(), Connection.js:194
emit(), events.js:203
Object.<anonymous>.Parser._resTagged(), Parser.js:175
Object.<anonymous>.Parser._parse(), Parser.js:139
Object.<anonymous>.Parser._tryread(), Parser.js:82
Parser._cbReadable(), Parser.js:53
emit(), events.js:203
emitReadable_(), _stream_readable.js:565
processTicksAndRejections(), task_queues.js:77
Async call from TickObject
init(), inspector_async_hook.js:21
emitInitNative(), async_hooks.js:134
emitInitScript(), async_hooks.js:341
TickObject(), task_queues.js:102
nextTick(), task_queues.js:130
emitReadable(), _stream_readable.js:557
addChunk(), _stream_readable.js:305
readableAddChunk(), _stream_readable.js:276
Readable.push(), _stream_readable.js:210
onStreamRead(), stream_base_commons.js:166
Async call from TCPWRAP
init(), inspector_async_hook.js:21
emitInitNative(), async_hooks.js:134
Socket.connect(), net.js:872
Object.<anonymous>.Connection.connect(), Connection.js:286
anonymous(), MailboxUtilityTest.ts:39
anonymous(), MailboxUtilityTest.ts:23
asyncJestTest(), jasmineAsyncInstall.js:102
anonymous(), queueRunner.js:43
mapper(), queueRunner.js:26
anonymous(), queueRunner.js:73
Async call from Promise.then
anonymous(), queueRunner.js:73
queueRunner(), queueRunner.js:72
queueRunnerFactory(), Env.js:277
execute(), Spec.js:169
fn(), treeProcessor.js:69
anonymous(), queueRunner.js:43
mapper(), queueRunner.js:26
anonymous(), queueRunner.js:73
Async call from Promise.then
anonymous(), queueRunner.js:73
queueRunner(), queueRunner.js:72
queueRunnerFactory(), Env.js:277
anonymous(), treeProcessor.js:79
asyncGeneratorStep(), treeProcessor.js:13
_next(), treeProcessor.js:33
anonymous(), treeProcessor.js:38
anonymous(), treeProcessor.js:30
fn(), treeProcessor.js:89
anonymous(), queueRunner.js:43
mapper(), queueRunner.js:26
anonymous(), queueRunner.js:73
Async call from Promise.then
anonymous(), queueRunner.js:73
queueRunner(), queueRunner.js:72
queueRunnerFactory(), Env.js:277
anonymous(), treeProcessor.js:79
asyncGeneratorStep(), treeProcessor.js:13
_next(), treeProcessor.js:33
anonymous(), treeProcessor.js:38
anonymous(), treeProcessor.js:30
fn(), treeProcessor.js:89
treeProcessor(), treeProcessor.js:122
anonymous(), Env.js:343
asyncGeneratorStep(), Env.js:36
_next(), Env.js:56
anonymous(), Env.js:61
anonymous(), Env.js:53
anonymous(), Env.js:388
anonymous(), index.js:203
asyncGeneratorStep(), index.js:27
_next(), index.js:47
anonymous(), index.js:52
anonymous(), index.js:44
_jasmine(), index.js:207
jasmine2(), index.js:60
anonymous(), runTest.js:385
asyncGeneratorStep(), runTest.js:161
_next(), runTest.js:181
Async call from Promise.then
asyncGeneratorStep(), runTest.js:170
_next(), runTest.js:181
anonymous(), runTest.js:186
anonymous(), runTest.js:178
_runTestInternal(), runTest.js:445
runTestInternal(), runTest.js:225
anonymous(), runTest.js:460
asyncGeneratorStep(), runTest.js:161
_next(), runTest.js:181
anonymous(), runTest.js:186
anonymous(), runTest.js:178
_runTest(), runTest.js:481
runTest(), runTest.js:449
anonymous(), index.js:159
asyncGeneratorStep(), index.js:61
_next(), index.js:81
Async call from Promise.then
asyncGeneratorStep(), index.js:70
_next(), index.js:81
anonymous(), index.js:86
anonymous(), index.js:78
Async call from Promise.then
anonymous(), index.js:150
anonymous(), index.js:11
run(), index.js:10
anonymous(), index.js:62
anonymous(), index.js:148
anonymous(), index.js:146
asyncGeneratorStep(), index.js:61
_next(), index.js:81
anonymous(), index.js:86
anonymous(), index.js:78
_createInBandTestRun(), index.js:167
anonymous(), index.js:123
asyncGeneratorStep(), index.js:61
_next(), index.js:81
anonymous(), index.js:86
anonymous(), index.js:78
runTests(), index.js:137
anonymous(), TestScheduler.js:353
asyncGeneratorStep(), TestScheduler.js:131
_next(), TestScheduler.js:151
Async call from Promise.then
asyncGeneratorStep(), TestScheduler.js:140
_next(), TestScheduler.js:151
anonymous(), TestScheduler.js:156
anonymous(), TestScheduler.js:148
scheduleTests(), TestScheduler.js:387
anonymous(), runJest.js:418
asyncGeneratorStep(), runJest.js:148
_next(), runJest.js:168

Stack
anonymous(), MailboxUtilityTest.ts:32
onceWrapper(), events.js:291
emit(), events.js:203
_onError(), Connection.js:151
emit(), events.js:203
emitErrorNT(), destroy.js:91
emitErrorAndCloseNT(), destroy.js:59
processTicksAndRejections(), task_queues.js:77
Async call from TickObject
init(), inspector_async_hook.js:21
emitInitNative(), async_hooks.js:134
emitInitScript(), async_hooks.js:341
TickObject(), task_queues.js:102
nextTick(), task_queues.js:130
anonymous(), destroy.js:43
Socket._destroy(), net.js:595
destroy(), destroy.js:37
onStreamRead(), stream_base_commons.js:183
Async call from TLSWRAP
init(), inspector_async_hook.js:21
emitInitNative(), async_hooks.js:134
TLSSocket._wrapHandle(), _tls_wrap.js:514
TLSSocket(), _tls_wrap.js:412
connect(), _tls_wrap.js:1405
anonymous(), Connection.js:1708
Object.<anonymous>.Connection._resTagged(), Connection.js:1535
anonymous(), Connection.js:194
emit(), events.js:203
Object.<anonymous>.Parser._resTagged(), Parser.js:175
Object.<anonymous>.Parser._parse(), Parser.js:139
Object.<anonymous>.Parser._tryread(), Parser.js:82
Parser._cbReadable(), Parser.js:53
emit(), events.js:203
emitReadable_(), _stream_readable.js:565
processTicksAndRejections(), task_queues.js:77
Async call from TickObject
init(), inspector_async_hook.js:21
emitInitNative(), async_hooks.js:134
emitInitScript(), async_hooks.js:341
TickObject(), task_queues.js:102
nextTick(), task_queues.js:130
emitReadable(), _stream_readable.js:557
addChunk(), _stream_readable.js:305
readableAddChunk(), _stream_readable.js:276
Readable.push(), _stream_readable.js:210
onStreamRead(), stream_base_commons.js:166
Async call from TCPWRAP
init(), inspector_async_hook.js:21
emitInitNative(), async_hooks.js:134
Socket.connect(), net.js:872
Object.<anonymous>.Connection.connect(), Connection.js:286
anonymous(), MailboxUtilityTest.ts:39
anonymous(), MailboxUtilityTest.ts:23
asyncJestTest(), jasmineAsyncInstall.js:102
anonymous(), queueRunner.js:43
mapper(), queueRunner.js:26
anonymous(), queueRunner.js:73
Async call from Promise.then
anonymous(), queueRunner.js:73
queueRunner(), queueRunner.js:72
queueRunnerFactory(), Env.js:277
execute(), Spec.js:169
fn(), treeProcessor.js:69
anonymous(), queueRunner.js:43
mapper(), queueRunner.js:26
anonymous(), queueRunner.js:73
Async call from Promise.then
anonymous(), queueRunner.js:73
queueRunner(), queueRunner.js:72
queueRunnerFactory(), Env.js:277
anonymous(), treeProcessor.js:79
asyncGeneratorStep(), treeProcessor.js:13
_next(), treeProcessor.js:33
anonymous(), treeProcessor.js:38
anonymous(), treeProcessor.js:30
fn(), treeProcessor.js:89
anonymous(), queueRunner.js:43
mapper(), queueRunner.js:26
anonymous(), queueRunner.js:73
Async call from Promise.then
anonymous(), queueRunner.js:73
queueRunner(), queueRunner.js:72
queueRunnerFactory(), Env.js:277
anonymous(), treeProcessor.js:79
asyncGeneratorStep(), treeProcessor.js:13
_next(), treeProcessor.js:33
anonymous(), treeProcessor.js:38
anonymous(), treeProcessor.js:30
fn(), treeProcessor.js:89
treeProcessor(), treeProcessor.js:122
anonymous(), Env.js:343
asyncGeneratorStep(), Env.js:36
_next(), Env.js:56
anonymous(), Env.js:61
anonymous(), Env.js:53
anonymous(), Env.js:388
anonymous(), index.js:203
asyncGeneratorStep(), index.js:27
_next(), index.js:47
anonymous(), index.js:52
anonymous(), index.js:44
_jasmine(), index.js:207
jasmine2(), index.js:60
anonymous(), runTest.js:385
asyncGeneratorStep(), runTest.js:161
_next(), runTest.js:181
Async call from Promise.then
asyncGeneratorStep(), runTest.js:170
_next(), runTest.js:181
anonymous(), runTest.js:186
anonymous(), runTest.js:178
_runTestInternal(), runTest.js:445
runTestInternal(), runTest.js:225
anonymous(), runTest.js:460
asyncGeneratorStep(), runTest.js:161
_next(), runTest.js:181
anonymous(), runTest.js:186
anonymous(), runTest.js:178
_runTest(), runTest.js:481
runTest(), runTest.js:449
anonymous(), index.js:159
asyncGeneratorStep(), index.js:61
_next(), index.js:81
Async call from Promise.then
asyncGeneratorStep(), index.js:70
_next(), index.js:81
anonymous(), index.js:86
anonymous(), index.js:78
Async call from Promise.then
anonymous(), index.js:150
anonymous(), index.js:11
run(), index.js:10
anonymous(), index.js:62
anonymous(), index.js:148
anonymous(), index.js:146
asyncGeneratorStep(), index.js:61
_next(), index.js:81
anonymous(), index.js:86
anonymous(), index.js:78
_createInBandTestRun(), index.js:167
anonymous(), index.js:123
asyncGeneratorStep(), index.js:61
_next(), index.js:81
anonymous(), index.js:86
anonymous(), index.js:78
runTests(), index.js:137
anonymous(), TestScheduler.js:353
asyncGeneratorStep(), TestScheduler.js:131
_next(), TestScheduler.js:151
It's a pain to manage those locally, since the failures are inconsistent and close handler comes through with failed: false as if there's no error.
One way to manage these is to use a complex once-like pattern, which would install and remove listeners. Otherwise, by simply removing all error listeners prior calling end, which doesn't feel like the right thing to do.
The argument passed to 'close' event handlers is merely what's passed from node core and is more of a historical thing.
I'm not sure I understand the problem though, you should always handle unexpected errors. Why are you concerned about having to removing the event handlers?
I'm not very familiar with the underlying api and what supposed to be happening, but pretty sure it shouldn't end with an error in this case. At the same time I do want to know of any errors, but you are right, this is more of an ideological case than practical.
I'm using this in a cli app and wrapping the module calls into promises to make use of the async and await. For some reason the code fails when the error callback fires and rejects the already resolved promise. From what I understand, failing the already resolved promise shouldn't affect it, but it somehow causes the cli app to fail. And without closing the stream the app never finishes.
I ended up handling those cases on per-promise basis, which seems to work smoothly so far, but it's a lot of boilerplate for what should work out of the box. From what you're saying I understand it's not the project related issue? Should it be reported else where?
If the issue is only present with Promises, then that's outside the scope of this project.
The messed up promise is the consequence, not the cause. The problem is with the imap package (or a dependency) randomly sending an error event after the close event when end()ing it.
The isolated code above illustrates this. Like said, this doesn't happen all the time, but often and consistently with different services.
Not sure if it is connected, but I have a software running against two email service providers. Calling imap.end() triggers "end" and "close" events if connected to server #1, but only "close" event in case of server #2. Only difference is username, password and email server name.