Repository navigation
AzurePipelinesCredential does async over sync (over async) causing problems in AMQP tests #44519
Copy link
Copy link
Open
Labels
Azure.Coreazure-coreazure-coreAzure.IdentityClientThis issue points to a problem in the data-plane of the library.This issue points to a problem in the data-plane of the library.bugThis issue requires a change to an existing behavior in the product in order to be resolved.This issue requires a change to an existing behavior in the product in order to be resolved.needs-team-attentionWorkflow: This issue needs attention from Azure service team or SDK teamWorkflow: This issue needs attention from Azure service team or SDK team
Milestone
Description
AMQP has a specific threading model and gets token on a thread that can't be blocked. It uses async getToken API.
In the case of AzurePipelinesCredential this results in something like this
06 Mar 2025 02:34:28,193 [reactor-executor-1] ERROR com.azure.core.http.netty.NettyAsyncHttpClient - block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-executor-1
java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-executor-1
at reactor.core@3.4.41/reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:83)
at reactor.core@3.4.41/reactor.core.publisher.Mono.block(Mono.java:1742)
at com.azure.http.netty@1.15.10/com.azure.core.http.netty.NettyAsyncHttpClient.sendSync(NettyAsyncHttpClient.java:195)
at com.azure.core@1.55.2/com.azure.core.http.HttpPipelineNextSyncPolicy.processSync(HttpPipelineNextSyncPolicy.java:51)
at com.azure.core@1.55.2/com.azure.core.http.policy.HttpLoggingPolicy.processSync(HttpLoggingPolicy.java:175)
at com.azure.core@1.55.2/com.azure.core.http.HttpPipelineNextSyncPolicy.processSync(HttpPipelineNextSyncPolicy.java:53)
at com.azure.core@1.55.2/com.azure.core.implementation.http.policy.InstrumentationPolicy.processSync(InstrumentationPolicy.java:101)
at com.azure.core@1.55.2/com.azure.core.http.HttpPipelineNextSyncPolicy.processSync(HttpPipelineNextSyncPolicy.java:53)
at com.azure.core@1.55.2/com.azure.core.http.policy.RetryPolicy.attemptSync(RetryPolicy.java:217)
at com.azure.core@1.55.2/com.azure.core.http.policy.RetryPolicy.processSync(RetryPolicy.java:161)
at com.azure.core@1.55.2/com.azure.core.http.HttpPipelineNextSyncPolicy.processSync(HttpPipelineNextSyncPolicy.java:53)
at com.azure.core@1.55.2/com.azure.core.http.policy.AddHeadersPolicy.processSync(AddHeadersPolicy.java:66)
at com.azure.core@1.55.2/com.azure.core.http.HttpPipelineNextSyncPolicy.processSync(HttpPipelineNextSyncPolicy.java:53)
at com.azure.core@1.55.2/com.azure.core.http.policy.HttpPipelineSyncPolicy.processSync(HttpPipelineSyncPolicy.java:51)
at com.azure.core@1.55.2/com.azure.core.http.policy.UserAgentPolicy.processSync(UserAgentPolicy.java:174)
at com.azure.core@1.55.2/com.azure.core.http.HttpPipelineNextSyncPolicy.processSync(HttpPipelineNextSyncPolicy.java:53)
at com.azure.core@1.55.2/com.azure.core.http.HttpPipeline.sendSync(HttpPipeline.java:138)
at com.azure.identity.AzurePipelinesCredential.lambda$new$0(AzurePipelinesCredential.java:80)
at com.azure.identity.implementation.IdentityClientBase.getConfidentialClient(IdentityClientBase.java:232)
at com.azure.identity.implementation.IdentityClient.lambda$getConfidentialClientApplication$5(IdentityClient.java:152)
at reactor.core@3.4.41/reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:45)
at reactor.core@3.4.41/reactor.core.publisher.MonoCacheTime.subscribeOrReturn(MonoCacheTime.java:143)
at reactor.core@3.4.41/reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:57)
at reactor.core@3.4.41/reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157)
at reactor.core@3.4.41/reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1839)
at reactor.core@3.4.41/reactor.core.publisher.MonoCacheInvalidateIf$CoordinatorSubscriber.onNext(MonoCacheInvalidateIf.java:319)
at reactor.core@3.4.41/reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:126)
at reactor.core@3.4.41/reactor.core.publisher.SerializedSubscriber.onNext(SerializedSubscriber.java:99)
at reactor.core@3.4.41/reactor.core.publisher.FluxRetryWhen$RetryWhenMainSubscriber.onNext(FluxRetryWhen.java:174)
at reactor.core@3.4.41/reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1839)
at reactor.core@3.4.41/reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:249)
at reactor.core@3.4.41/reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.complete(MonoIgnoreThen.java:292)
at reactor.core@3.4.41/reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onNext(MonoIgnoreThen.java:187)
at reactor.core@3.4.41/reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:236)
at reactor.core@3.4.41/reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:203)
at reactor.core@3.4.41/reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260)
at reactor.core@3.4.41/reactor.core.publisher.SerializedSubscriber.onComplete(SerializedSubscriber.java:146)
at reactor.core@3.4.41/reactor.core.publisher.FluxTimeout$TimeoutMainSubscriber.onComplete(FluxTimeout.java:234)
at reactor.core@3.4.41/reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onComplete(FluxSwitchIfEmpty.java:85)
at reactor.core@3.4.41/reactor.core.publisher.MonoNext$NextSubscriber.onComplete(MonoNext.java:102)
at reactor.core@3.4.41/reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:83)
at reactor.core@3.4.41/reactor.core.publisher.FluxFilter$FilterSubscriber.onNext(FluxFilter.java:113)
at reactor.core@3.4.41/reactor.core.publisher.EmitterProcessor.drain(EmitterProcessor.java:537)
at reactor.core@3.4.41/reactor.core.publisher.EmitterProcessor.tryEmitNext(EmitterProcessor.java:343)
at reactor.core@3.4.41/reactor.core.publisher.SinkManySerialized.tryEmitNext(SinkManySerialized.java:100)
at reactor.core@3.4.41/reactor.core.publisher.InternalManySink.emitNext(InternalManySink.java:27)
at com.azure.core.amqp.implementation.RequestResponseChannel.updateEndpointState(RequestResponseChannel.java:496)
because of this code
Line 80 in fe75c7d
| try (HttpResponse response = httpPipeline.sendSync(request, Context.NONE)) { |
that does sync over async (and back to async under because of Netty).
While this affects tests only, it'd be nice to avoid async over sync and minimize issues like this.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Azure.Coreazure-coreazure-coreAzure.IdentityClientThis issue points to a problem in the data-plane of the library.This issue points to a problem in the data-plane of the library.bugThis issue requires a change to an existing behavior in the product in order to be resolved.This issue requires a change to an existing behavior in the product in order to be resolved.needs-team-attentionWorkflow: This issue needs attention from Azure service team or SDK teamWorkflow: This issue needs attention from Azure service team or SDK team
Type
Projects
- StatusShow more project fieldsNo status
- StatusShow more project fieldsBacklog
Activity
github-actions commentedon Mar 6, 2025
Thank you for your feedback. Tagging and routing to the team member best able to assist.
lmolkova commentedon Mar 6, 2025
Based on offline discussion with Alan Zimmer (@alzimmermsft) and Anu Thomas (@anuchandy),
AzurePipelineCredentialsis used in production applications.Plus there is a reactor contract for Mono that underlying work should not block the caller/subscriber and recommendation to wrap blocking calls and execute them on bounded elastic scheduler - https://projectreactor.io/docs/core/release/reference/faq.html#faq.wrap-blocking
So it's important to fix it for all possible users of
AzurePipelineCredentialsand either implement a fully async pipeline or follow https://projectreactor.io/docs/core/release/reference/faq.html#faq.wrap-blocking if that's impossible