Hi. I am setting up Sentry on asp.net Core and I am getting the following message: Anyone know how to resolve w/o having to set the option in the Startup.cs?
System.InvalidOperationException Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.
I don’t see this having to be set in your examples, what is the workaround, or do I have to set that option?
At what point is this happening? The sdk can do a file I/O at startup time to check for crashed reports stored in the disk in case the process is crashing right after starting. You can opt out via InitFlushTimeout setting it to Zero. But I’d expect that to only be needed if offline caching is enabled (via CachingDirectoryPath being set to a path, did by aby chance you set this?)
This feature enables request buffering so in the event of an error, sentry can read the request body which would otherwise have been consumed while processing the request (I.e. Binding model). The sdk uses a sync api to read from the stream but at that point the stream would be in memory, unless somehow the error happened before your controller got the request, for example a broken Middleware that fails even before reading the body. This was discussed in the past here:
The SDK Capture API is sync. If you for example call LogError(Ex) there’s no way to have a non blocking call in there, and given the description above about it being a false positive (if you processed the request, so model binding happened)
It shouldn’t break anything since the body would be already cached when we read it,. But even if it did block, you’d have a potential blocking call only when an error happens (we only attach the body when an error happens serving the request),
What’s the Content-Type you’re trying to capture? Did you enable the SDK debugging logs with Debug=true ?
I opened that ticket and I turned the debug on, and this is the error and stack trace I see in my output log;
Sentry.ISentryClient: Error: Failed to extract body.
System.ObjectDisposedException: Cannot access a closed Stream.
at System.IO.MemoryStream.get_Position()
at Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream.get_Position()
at Sentry.Extensibility.BaseRequestPayloadExtractor.ExtractPayload(IHttpRequest request) in /_/src/Sentry/Extensibility/BaseRequestPayloadExtractor.cs:line 28
at Sentry.Extensibility.RequestBodyExtractionDispatcher.ExtractPayload(IHttpRequest request) in /_/src/Sentry/Extensibility/RequestBodyExtractionDispatcher.cs:line 57
at Sentry.AspNetCore.ScopeExtensions.SetBody(Scope scope, HttpContext context, SentryAspNetCoreOptions options) in /_/src/Sentry.AspNetCore/ScopeExtensions.cs:line 160
at Sentry.AspNetCore.ScopeExtensions.Populate(Scope scope, HttpContext context, SentryAspNetCoreOptions options) in /_/src/Sentry.AspNetCore/ScopeExtensions.cs:line 59
Sentry.ISentryClient: Error: Failed to extract body.
The SDK captures the request object via a closure in the request pipeline. If you kick off a job to a. background thread and an event is sent, it might try to read the request data once ASP.NET Core already disposed it. The reason it captures the object and reads it only if an event is captured is to spare the overhead of reading the request data into Sentry’s scope in case there’s no event being sent out. The request data is only read into Sentry’s scope once. So if you capture an event before kicking off some background work, the scope will already be filled so this error log entry wouldn’t show up.
In short: ASP.NET Core doesn’t allow reading the request body on a background thread.
You can work around this and coincidently I’ve done that in the past. Basically you read the request data within the request thread, before you spawn the background work. Then when you capture from the background thread, the data will be already in Sentry.
There’s no ‘built-in’ way to cover this use-case but I’ve had to do this work around myself too: