flyd icon indicating copy to clipboard operation
flyd copied to clipboard

Internal state breaks on errors within an `on` listener?

Open agj opened this issue 7 years ago • 4 comments

I was getting the weirdest error, and it took me a while, but I reduced my code to this:

const flyd = require('flyd');

const run = assert => {
	process.on('uncaughtException', (e) => {
		console.log('Uncaught exception:', e);
	});

	const letter = flyd.stream('a');
	const uppercaseLetter = flyd.map(l => l.toUpperCase(), letter);

	console.log('Weird stuff here:', letter(), uppercaseLetter());

	setTimeout(() => letter('b'), 0);

	flyd.on(l => { if (l === 'b') throw "Error on purpose." }, letter);
};

run();
setTimeout(run, 0);

For which I get this output (Node v9.7.1):

Weird stuff here: a A
Uncaught exception: Error on purpose.
Weird stuff here: a undefined

Notice how the letter stream has the correct initial value both times, while the mapped stream uppercaseLetter breaks after an exception is thrown. Both times the streams and everything else are recreated from scratch, so my guess is that something seriously breaks in flyd's internal state when an exception is thrown while running on listeners...

By the way, thanks for flyd, and keep up the good work!

agj avatar Mar 07 '18 05:03 agj

As of now you need to handle errors on your side.

When an error occurs in a stream body the internal state of flyd is corrupted (the inStream variable). There've been some discussions about how flyd should handle errors but nothing conclusive as of yet.

nordfjord avatar Mar 07 '18 09:03 nordfjord

By "handle errors on your side", do you mean wrapping the contents of every subscribing function in a try/catch block? Hm.

For what is worth, this case arose in my intentionally breaking stuff for my tests, and while the code is supposed to exit the process, for the tests of course I'm trying to avoid that.

agj avatar Mar 07 '18 13:03 agj

Duplicate of #164

For now, flyd gives atomic updates without any error handling.

Exceptions inside a stream subscription function have no guarantee that any stream in that dependency graph will be valid in the end.

For code that can fail, you'll need to wrap it in a try...catch -- this includes subscribed 'on' functions.

c-dante avatar Mar 07 '18 15:03 c-dante

Okay, thank you.

agj avatar Mar 07 '18 15:03 agj