Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead

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?)

It happens on the first Put request. Get requests seem to work fine

What version of the sdk are you using?
Did you opt in to include the request body?

Sdk from NuGet 3.8.3 and Yes, it does look like I did.

I coped the settings for the appSettings from a setup page and it has this setting.

"MaxRequestBodySize": "Always",

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)

So, what are the solutions to make the sdk work for post/put requests?

You can set AllowSynchronousIO to true to get rid of the warning. Also since as discussed above it’s a false positive.

Or if you don’t want that, you can remove the request body attaching feature (it’s off by default).

That seemed to get rid of the error message, but still does not show the body of the post

How many customers have that turned on? It seems like it would be helpful, but I don’t want to break our Async communications.

And another question:
our full route is https://ourservername.com/UserAPI/v1/Authentication/AuthenticateUser

but the performance logs only show “v1/Authentication/AuthenticateUser” and give no refrence to UserApi. Is there a way to capture that also?

Thanks,
Michael

Sounds like a bug (maybe because of Areas?) Can you please raise an issue on the repo to discuss there? GitHub - getsentry/sentry-dotnet: Sentry SDK for .NET

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.

@bruno-garcia ^^

Looks like the request was already closed when the SDK tried to capture the error.
Was that error captured on a background thread?

What do you mean a background thread? It came in through a .Net core webapi call, then after that, the it was processed it another thread using Async.

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.

Other than capturing the error of trying to read it and logging via the diagnostic logger, there’s no negative side effect here. It used to show up on the breadcrumbs list but this was removed a few versions ago.

There’s more context in previous issues such as:

So, are you saying there is no way to capture the body if we use async processing?

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:

  1. I capture a message right before I do Task.Run with level Debug: symbol-collector/BatchFinalizer.cs at e31753b68380e830bec400a97c879ff97d0f6bd9 · getsentry/symbol-collector · GitHub

But I drop all events with level Debug: symbol-collector/Program.cs at e31753b68380e830bec400a97c879ff97d0f6bd9 · getsentry/symbol-collector · GitHub