Skip to content

Root cause exception info gets lost #1235

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
MSACATS opened this issue Jun 18, 2020 · 2 comments
Closed

Root cause exception info gets lost #1235

MSACATS opened this issue Jun 18, 2020 · 2 comments
Milestone

Comments

@MSACATS
Copy link

MSACATS commented Jun 18, 2020

I'm having trouble getting proper stack traces / exception root cause info. Below is an example test:
I have a multi-value observable and I call "SingleAsync" on it, which raises an exception that there is more than one element in the sequence. However, no matter how I try, I can never get the real location of that exception, which makes it basically impossible to track down in our actual system. For example all I get is:

when I await the Observable:

System.InvalidOperationException: Sequence contains more than one element.
at System.Reactive.PlatformServices.ExceptionServicesImpl.Rethrow(Exception exception) in /_/Rx.NET/Source/src/System.Reactive/Internal/ExceptionServicesImpl.cs:line 16

when I await the Observable.ToTask:

System.InvalidOperationException: Sequence contains more than one element.
at TestAwaitOnMultipleElements() in \ReactiveTests.cs:line 29

(i.e. the await task line, not the actual SingleAsync() line)

when I use the Subscribe:

System.InvalidOperationException: Sequence contains more than one element.
(i.e. no stack trace at all)

This is the test code:

[TestMethod]
public async Task TestAwaitOnMultipleElements()
{
	IObservable<int> multiElementObservable = OtherMethodToVerifyWeCanFindTheCause();

	await multiElementObservable;

	var task = multiElementObservable.ToTask();
	await task;

	TaskCompletionSource<Unit> taskCompletion = new TaskCompletionSource<Unit>();
	multiElementObservable.Subscribe(
			i => Trace.TraceInformation("Element {0}", i.ToString()),
			e =>
			{
				Trace.TraceError(e.ToString());
				taskCompletion.SetException(e);
			},
			() => taskCompletion.SetResult(Unit.Default));
	await taskCompletion.Task;
}

private static IObservable<int> OtherMethodToVerifyWeCanFindTheCause()
{
	var multiElementObservable = Observable.Range(0, 2);

	multiElementObservable = multiElementObservable
		.Do(i => Trace.TraceInformation("Element {0}", i.ToString()))
		.SingleAsync(); //this will be an error because there are multiple elements
	return multiElementObservable;
}
@bartdesmet
Copy link
Collaborator

Some improvement can likely be made for operators that create an exception object out of nowhere. Those lack stack traces because they don't really got thrown; they're just exception objects flowing into OnError calls. Will have a look for the upcoming release.

@bartdesmet
Copy link
Collaborator

A small improvement has been made. The very nature of exception propagation in Rx limits the context provided in a stack trace in cases where an operator such as SingleAsync propagates an exception of its own. However, with the change made (see PR linked above), there will be at least a hint at the operator that caused the exception.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants