graphql-platform
graphql-platform copied to clipboard
HotChocolate: Subscription errors are swallowed
Describe the bug If an exception occurs in the subscription backend (for example related to the JSON serialization done during the Redis transport), the HC Server will simply swallow the error, and the subscription will be terminated.
On the client side, an error like this will be seen:
[GraphQL error]: Message: Unexpected Execution Error, Location: undefined, Path: undefined
On the server side, nothing - even if you have configured an errorfilter.
To Reproduce
Configure a subscription, subscribe to it, then publish a message to the topic containing an object that fails serialization (in my case, an object with a property of type JsonDocument
).
Expected behavior Properly propagating the exception, so that it can be picked up by IErrorFilter, for example.
Additional context The only current option AFAIK that allows you to catch such errors, is to make the subscription resolver very verbose like the below:
var stream = await eventReceiver.SubscribeAsync<string, Foo>(
"foo-topic", cancellationToken);
var enumerator = stream.ReadEventsAsync().GetAsyncEnumerator(cancellationToken);
var hasResult = true;
while (hasResult)
{
Foo? result;
try
{
hasResult = await enumerator.MoveNextAsync().ConfigureAwait(false);
result = hasResult
? enumerator.Current
: null;
}
catch (Exception ex)
{
result = null;
}
if (result != null)
{
yield return result;
}
}
This also happens when using IObservable and the IObservable rises an exception when producing an element. In this specific case, the error is completely swallowed and nothing (nor errors, no null, no connection closing) is sent to the client.
For example, with a subscription in this (fake) form:
public IObservable<Customer> SubscribeToCustomerChanges(long key) {
return Observable.FromAsync(async ct => {
try {
var session = _globalSessionFactory.CreateReadOnlySession();
return await session.LoadAsync(key, cancellationToken: ct).ConfigureAwait(false);
}
catch (CannotLoadObjectsException ex) {
throw new QueryException(ex.Message);
}
});
}
When an invalid key is passed, no error is sent to the client. Using Banana Cake Pop in Asp.Net Core nothing is shown, and the subscription request apparently keeps waiting for other updates. With a valid key, the subscription correctly sends the customer data. This is the sample query:
subscription {
subscribeToCustomerChanges(key: 9999999) {
oid,
name
}
}
AFAIK this is still valid. (Commenting to keep issue alive)
The issue here is that if the message is invalid it never gets to the execution as the error happens on the event stream.
With 13.4 we have improved insights and there os now an error on the diagnostic events.
ISubscriptionDiagnosticEvents.MessageProcessingError(string topicName, Exception error)
Overriding this on the diagnostic listener will allow errors to be captured.