Skip to content
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

Error under load "Detected use of the reactive Session from a different Thread..." #23324

Open
mklueh opened this issue Jan 31, 2022 · 30 comments
Labels
area/hibernate-reactive Hibernate Reactive kind/bug Something isn't working

Comments

@mklueh
Copy link
Contributor

mklueh commented Jan 31, 2022

Describe the bug

I'm using the reactive dependencies and I'm running into a use case, where I need to store events asynchronously when my REST endpoint gets hit, without blocking the REST call and delaying the response.

I thought, well, that's easy. Just use SmallRye Emitter, fire an event and the consumer should handle the storing, while the REST call returns the response. Easier said than done, I'm not getting this simple-sounding example to work without this error when I run a load test with up to 20 req/s (error happens much earlier).

2022-01-31 21:02:35,054 ERROR [com.exa.MyService] (vert.x-eventloop-thread-12) Failed to store event: java.lang.IllegalStateException: HR000069: Detected use of the reactive Session from a different Thread than the one which was used to open the reactive Session - this suggests an invalid integration; original thread: 'vert.x-eventloop-thread-11' current Thread: 'vert.x-eventloop-thread-12'
	at org.hibernate.reactive.common.InternalStateAssertions.assertCurrentThreadMatches(InternalStateAssertions.java:46)
	at org.hibernate.reactive.session.impl.ReactiveSessionImpl.threadCheck(ReactiveSessionImpl.java:154)
	at org.hibernate.reactive.session.impl.ReactiveSessionImpl.checkOpen(ReactiveSessionImpl.java:1557)
	at org.hibernate.internal.SessionImpl.contains(SessionImpl.java:2004)
	at org.hibernate.reactive.mutiny.impl.MutinySessionImpl.contains(MutinySessionImpl.java:104)
	at io.quarkus.hibernate.reactive.runtime.ReactiveSessionProducer_ProducerMethod_createMutinySession_1321d110ee9e92bda147899150401e0a136779c7_ClientProxy.contains(Unknown Source)
	at io.quarkus.hibernate.reactive.panache.common.runtime.AbstractJpaOperations.lambda$persist$1(AbstractJpaOperations.java:76)
	at io.smallrye.context.impl.wrappers.SlowContextualFunction.apply(SlowContextualFunction.java:21)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.performInnerSubscription(UniOnItemTransformToUni.java:68)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.onItem(UniOnItemTransformToUni.java:57)
	at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem$KnownItemSubscription.forward(UniCreateFromKnownItem.java:38)
	at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem$KnownItemSubscription.access$100(UniCreateFromKnownItem.java:26)
	at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem.subscribe(UniCreateFromKnownItem.java:23)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni.subscribe(UniOnItemTransformToUni.java:25)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransform.subscribe(UniOnItemTransform.java:22)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.performInnerSubscription(UniOnItemTransformToUni.java:81)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.onItem(UniOnItemTransformToUni.java:57)
	at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem$KnownItemSubscription.forward(UniCreateFromKnownItem.java:38)
	at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem$KnownItemSubscription.access$100(UniCreateFromKnownItem.java:26)
	at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem.subscribe(UniCreateFromKnownItem.java:23)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni.subscribe(UniOnItemTransformToUni.java:25)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniOnItemConsume.subscribe(UniOnItemConsume.java:30)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.groups.UniSubscribe.withSubscriber(UniSubscribe.java:50)
	at io.smallrye.mutiny.groups.UniSubscribe.with(UniSubscribe.java:111)
	at com.example.MyService.fireForget(MyService.java:20)
	at com.example.MyService_Subclass.fireForget$$superforward1(Unknown Source)
	at com.example.MyService_Subclass$$function$$1.apply(Unknown Source)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:54)
	at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.proceed(InvocationInterceptor.java:62)
	at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.monitor(InvocationInterceptor.java:49)
	at io.quarkus.arc.runtime.devconsole.InvocationInterceptor_Bean.intercept(Unknown Source)
	at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:41)
	at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:32)
	at com.example.MyService_Subclass.fireForget(Unknown Source)
	at com.example.MyService_ClientProxy.fireForget(Unknown Source)
	at com.example.MyService_SmallRyeMessagingInvoker_fireForget_f43d24ab1056a056837479d09bdcf5dd34fec4eb.invoke(Unknown Source)
	at io.smallrye.reactive.messaging.providers.AbstractMediator.invoke(AbstractMediator.java:91)
	at io.smallrye.reactive.messaging.providers.SubscriberMediator.lambda$processMethodReturningVoid$6(SubscriberMediator.java:171)
	at io.smallrye.context.impl.wrappers.SlowContextualSupplier.get(SlowContextualSupplier.java:21)
	at io.smallrye.mutiny.operators.uni.builders.UniCreateFromItemSupplier.subscribe(UniCreateFromItemSupplier.java:28)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniOnItemOrFailureFlatMap.subscribe(UniOnItemOrFailureFlatMap.java:27)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.converters.uni.UniToMultiPublisher$UniToMultiSubscription.request(UniToMultiPublisher.java:63)
	at io.smallrye.mutiny.operators.multi.MultiFlatMapOp$FlatMapInner.onSubscribe(MultiFlatMapOp.java:591)
	at io.smallrye.mutiny.converters.uni.UniToMultiPublisher.subscribe(UniToMultiPublisher.java:24)
	at io.smallrye.mutiny.groups.MultiCreate$1.subscribe(MultiCreate.java:161)
	at io.smallrye.mutiny.operators.multi.MultiFlatMapOp$FlatMapMainSubscriber.onItem(MultiFlatMapOp.java:191)
	at io.smallrye.mutiny.operators.multi.MultiMapOp$MapProcessor.onItem(MultiMapOp.java:50)
	at io.smallrye.mutiny.subscription.MultiSubscriber.onNext(MultiSubscriber.java:61)
	at io.smallrye.mutiny.subscription.SafeSubscriber.onNext(SafeSubscriber.java:98)
	at io.smallrye.mutiny.helpers.HalfSerializer.onNext(HalfSerializer.java:31)
	at io.smallrye.mutiny.helpers.StrictMultiSubscriber.onItem(StrictMultiSubscriber.java:83)
	at io.smallrye.mutiny.operators.multi.MultiOperatorProcessor.onItem(MultiOperatorProcessor.java:89)
	at io.smallrye.mutiny.operators.multi.builders.BufferItemMultiEmitter.drain(BufferItemMultiEmitter.java:118)
	at io.smallrye.mutiny.operators.multi.builders.BufferItemMultiEmitter.emit(BufferItemMultiEmitter.java:34)
	at io.smallrye.mutiny.operators.multi.builders.SerializedMultiEmitter.onItem(SerializedMultiEmitter.java:49)
	at io.smallrye.mutiny.operators.multi.builders.SerializedMultiEmitter.emit(SerializedMultiEmitter.java:139)
	at io.smallrye.reactive.messaging.providers.extension.ThrowingEmitter.emit(ThrowingEmitter.java:63)
	at io.smallrye.reactive.messaging.providers.extension.AbstractEmitter.emit(AbstractEmitter.java:161)
	at io.smallrye.reactive.messaging.providers.extension.EmitterImpl.send(EmitterImpl.java:29)
	at com.example.ExampleResource.lambda$callFetchEntityAndGreetAndLog$2(ExampleResource.java:45)
	at io.smallrye.context.impl.wrappers.SlowContextualFunction.apply(SlowContextualFunction.java:21)
	at io.smallrye.mutiny.groups.UniOnItem.lambda$call$2(UniOnItem.java:79)
	at io.smallrye.context.impl.wrappers.SlowContextualFunction.apply(SlowContextualFunction.java:21)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.performInnerSubscription(UniOnItemTransformToUni.java:68)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.onItem(UniOnItemTransformToUni.java:57)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.onItem(UniOnItemTransformToUni.java:60)
	at io.smallrye.mutiny.operators.uni.builders.DefaultUniEmitter.complete(DefaultUniEmitter.java:36)
	at io.smallrye.mutiny.groups.UniOnNull.lambda$failWith$1(UniOnNull.java:46)
	at io.smallrye.context.impl.wrappers.SlowContextualBiConsumer.accept(SlowContextualBiConsumer.java:21)
	at io.smallrye.mutiny.groups.UniOnItem.lambda$transformToUni$4(UniOnItem.java:178)
	at io.smallrye.context.impl.wrappers.SlowContextualConsumer.accept(SlowContextualConsumer.java:21)
	at io.smallrye.mutiny.operators.uni.builders.UniCreateWithEmitter.subscribe(UniCreateWithEmitter.java:22)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.performInnerSubscription(UniOnItemTransformToUni.java:81)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.onItem(UniOnItemTransformToUni.java:57)
	at io.smallrye.mutiny.operators.uni.UniOnItemConsume$UniOnItemComsumeProcessor.onItem(UniOnItemConsume.java:43)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.onItem(UniOnItemTransformToUni.java:60)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransform$UniOnItemTransformProcessor.onItem(UniOnItemTransform.java:43)
	at io.smallrye.mutiny.operators.uni.UniOperatorProcessor.onItem(UniOperatorProcessor.java:40)
	at io.smallrye.mutiny.operators.uni.builders.UniCreateFromCompletionStage$CompletionStageUniSubscription.forwardResult(UniCreateFromCompletionStage.java:63)
	at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863)
	at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841)
	at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
	at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2147)
	at io.vertx.core.Future.lambda$toCompletionStage$2(Future.java:360)
	at io.vertx.core.impl.future.FutureImpl$3.onSuccess(FutureImpl.java:141)
	at io.vertx.core.impl.future.FutureBase.emitSuccess(FutureBase.java:60)
	at io.vertx.core.impl.future.FutureImpl.tryComplete(FutureImpl.java:211)
	at io.vertx.core.impl.future.PromiseImpl.tryComplete(PromiseImpl.java:23)
	at io.vertx.sqlclient.impl.QueryResultBuilder.tryComplete(QueryResultBuilder.java:102)
	at io.vertx.sqlclient.impl.QueryResultBuilder.tryComplete(QueryResultBuilder.java:35)
	at io.vertx.core.Promise.complete(Promise.java:66)
	at io.vertx.core.Promise.handle(Promise.java:51)
	at io.vertx.core.Promise.handle(Promise.java:29)
	at io.vertx.core.impl.future.FutureImpl$3.onSuccess(FutureImpl.java:141)
	at io.vertx.core.impl.future.FutureBase.lambda$emitSuccess$0(FutureBase.java:54)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:503)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:833)

Reactive programming is relatively new to me, so it just could be that I'm missing something obvious I have overlooked in the examples.

Expected behavior

No response

Actual behavior

No response

How to Reproduce?

https://github.com/mklueh/quarkus-reproducer-reactive-hibernate-smallrye-messaging

I've created two load-testing scripts that are using k6 in Docker to test both endpoints. Both will fail.

  1. test-call.sh
  2. test-invoke.sh

Does not matter which, both lead to the same error.

Output of uname -a or ver

No response

Output of java -version

No response

GraalVM version (if different from Java)

No response

Quarkus version or git rev

2.6.3

Build tool (ie. output of mvnw --version or gradlew --version)

No response

Additional information

No response

@mklueh mklueh added the kind/bug Something isn't working label Jan 31, 2022
@geoand geoand changed the title Error under load "Detected use of the reactive Session from a different Thread than the one which was used to open the reactive Session - this suggests an invalid integration; original thread: 'vert.x-eventloop-thread-13' current Thread: 'vert.x-eventloop-thread-3'" Error under load "Detected use of the reactive Session from a different Thread..." Feb 1, 2022
@geoand geoand added area/hibernate-reactive Hibernate Reactive and removed triage/needs-triage labels Feb 1, 2022
@quarkus-bot
Copy link

quarkus-bot bot commented Feb 1, 2022

/cc @DavideD, @Sanne, @gavinking

@Sanne
Copy link
Member

Sanne commented Feb 1, 2022

Thanks for the report! We'll have a look. I didn't check the details but I suspect it might relate to #23300 - let's fix that one first, then verify.

@sunildparte
Copy link

I am facing exact same issue when load testing my quarkus application. My application is very similar to this quickstart project - https://github.com/quarkusio/quarkus-quickstarts/tree/main/hibernate-reactive-panache-quickstart. Is there any workaround until #23300 is fixed?

@Sanne
Copy link
Member

Sanne commented Feb 3, 2022

I am facing exact same issue when load testing my quarkus application. My application is very similar to this quickstart project - https://github.com/quarkusio/quarkus-quickstarts/tree/main/hibernate-reactive-panache-quickstart. Is there any workaround until #23300 is fixed?

I've described the "workaround" for that issue on it:

@mklueh
Copy link
Contributor Author

mklueh commented Feb 13, 2022

I was running into this problem again, but it seems that it is working at some places, and at others it is not.

workaround:

instead of

FileRef fileRef = new FileRef();

Uni<PanacheEntityBase>  uni = Panache.withTransaction(fileRef::persist)

//or

Uni<FileRef>  uni = Panache.withTransaction(()->fileRefRepository.persist(fileRef))

using this

FileRef fileRef = new FileRef();

Uni<FileRef> uni = sessionFactory.withTransaction(session -> session.persist(fileRef).onItem().transform(unused -> fileRef));

The workaround really helps, but is there any progress with this issue so far already @Sanne ?

@Sanne
Copy link
Member

Sanne commented Feb 22, 2022

hi @mklueh in that particular case I suspect you're hitting a very similar issue (but not the same) with scopes in reactive messaging. This should be fixed in Quarkus 2.7.2 - could you try it?

@bartwinski
Copy link

Hello @Sanne with the quarkus 2.7.5 Final we still facing this issue under load. Especially directly after quarkus startup. Without high load it works fine.
We are using reactive-hibernate with Postgres
We are using following approach: Panache.withTransaction {entity.persist()}
Using sessionFactory.withTransaction works also not.
The same exception is thrown: Failed to store event: java.lang.IllegalStateException: HR000069: Detected use of the reactive Session from a different Thread than the one which was used to open the reactive Session - this suggests an invalid integration; original thread: 'vert.x-eventloop-thread-11' current Thread: 'vert.x-eventloop-thread-12'

@zuochangqin
Copy link

zuochangqin commented May 10, 2022

Is there any update on this topic? Do I have to wrap every method that operates on the database with Panache. WithTransaction? Reactive Hibernate is not stable, and often causes errors.The quarkus version I use is 2.8.2.final.

@Sanne
Copy link
Member

Sanne commented May 10, 2022

Let me explain, Hibernate Reactive by design requires all operations to be executed from the same thread.

The exception "java.lang.IllegalStateException: HR000069: Detected use of the reactive Session from a different Thread than ..." literally means that we've detected illegal use of it, and we're throwing an exception on purpose so that integration problems can be detected (such integration problems would otherwise most likely lead to more serious issues, such as data inconsistencies being written).

If you have such issues, you're using it in the wrong context. If you can't strictly guarantee that your application is fully reactive and that each transaction is constrained within the same unique thread, you shouldn't use it; consider using Hiberante ORM blocking, which is more suited for non-blocking designs.

The reason Panache.withTransaction helps is because it offloads the entire "work" definition onto a vert.x worker thread; so even if you were running it on the wrong thread it will first switch to the right thread, then execute it correctly. This is not optimal in terms of efficiency, but helps straighetning integration with other components.

Also, please use the Mutiny based API of Hibernate Reactive. When using CompletionStage it gets surprisingly tricky to get the threading model correct.

Reactive Hibernate is not stable, and often causes errors.

Well as I mentioned we throw these exceptions on purpose - not because it's unstable but most likely because it's not being used correctly.

I'll have another look at the reproducer of this issue - pretty sure something is wrong in the integration. Other people commenting here... please open a different issue and attach a reproducer, I can't help you otherwise - sorry :/

@DavideD
Copy link
Contributor

DavideD commented May 26, 2022

I've tested the original testcase with Quarkus 2.9.2 and I cannot see the error anymore.

Still, I'm not sure how one is supposed to implement this use-case.

This is what the test case is trying to achieve:

  1. Http get to a Rest service
  2. The service look for an entity in the db by id
  3. When the entity is found emit an event in a channel
  4. The service listening to the channel will create a new event in the db

Point 4 is implemented this way:

@Slf4j
@ApplicationScoped
public class MyService {

    @Incoming(Event.FIRE_AND_FORGET)
    public void fireForget(Event event) {
        Panache.withTransaction(event::persist)
                .onFailure().invoke(throwable -> log.error("Failed to store event", throwable))
                .subscribe().with(panacheEntityBase -> {
                });
    }
}

Is this the right approach to use?

When I've upgraded to Quarkus 2.9.2 I had to add @ActivateRequestContext :

@Slf4j
@ApplicationScoped
@ActivateRequestContext 
public class MyService {

    @Incoming(Event.FIRE_AND_FORGET)
    public void fireForget(Event event) {
		Panache.withTransaction( event::persist )
				.onFailure().invoke( throwable -> log.error( "Failed to store event", throwable ) )
				.subscribe().with( System.out::println, System.err::println );
    }
}

I'm asking because it doesn't seem to work and I get the error

2022-05-26 13:43:02,487 ERROR [com.exa.MyService] (vert.x-eventloop-thread-1) Failed to store event: java.lang.IllegalStateException: HR000060: Session is closed                                                    

I think the error the issue is referring to has been solved but it would be nice to fix the testcase so that it works

@inngvar
Copy link

inngvar commented Sep 19, 2022

"workaround" you can try:

  • in application properties set quarkus.vertx.event-loops-pool-size=1
  • or disable state assertions for you own risk System.setProperty("org.hibernate.reactive.common.InternalStateAssertions.ENFORCE", "false")

@DavideD
Copy link
Contributor

DavideD commented Sep 20, 2022

I'm not sure that's the right approach.
Probably, the session closed error happens because the session is closed when returning from fireAndForget. But because the content is async, it might happen that it's closed too soon, before withTransaction is even executed.

I think a better solution would is to use the Hibernate Session factory directly. But I need to test it.

@DavideD
Copy link
Contributor

DavideD commented Sep 20, 2022

If I use the Hibernate Reactive session factory, I see this error:

022-09-20 09:01:03,807 ERROR [org.jbo.res.rea.com.cor.AbstractResteasyReactiveContext] (vert.x-eventloop-thread-2) Request failed: java.lang.IllegalStateException: The current operation requires a safe (isolated) Vert.x sub-context, but the current context hasn't been flagged as such. You can still use Hibernate Reactive, you just need to avoid using the methods which implicitly require accessing the stateful context, such as MutinySessionFactory#withTransaction and #withSession.
        at io.quarkus.vertx.core.runtime.context.VertxContextSafetyToggle.checkIsSafe(VertxContextSafetyToggle.java:89)
        at io.quarkus.vertx.core.runtime.context.VertxContextSafetyToggle.validateContextIfExists(VertxContextSafetyToggle.java:72)
        at io.quarkus.hibernate.reactive.runtime.customized.CheckingVertxContext.get(CheckingVertxContext.java:46)
        at org.hibernate.reactive.mutiny.impl.MutinySessionFactoryImpl.withSession(MutinySessionFactoryImpl.java:189)

@DavideD
Copy link
Contributor

DavideD commented Sep 20, 2022

This implementation should work though:

@Slf4j
@ApplicationScoped
public class MyService {

    @Inject
    Mutiny.SessionFactory sf;

    @Incoming(Event.FIRE_AND_FORGET)
    public void fireForget(Event event) {
        sf.openSession().chain(session -> session
                        .withTransaction( tx -> session.persist( event ) )
                        .eventually( session::close )
                )
                .onFailure().invoke(throwable -> log.error("Failed to store event", throwable))
                .subscribe().with(panacheEntityBase -> {
                });
    }
}

@kavishkamk
Copy link

Hi. I am facing the same issue. I am currently using 2.16.5.Final. in new versions is this solved? or I have to go with some kind of blocking operation as suggested.

@DavideD
Copy link
Contributor

DavideD commented Aug 24, 2023

@kavishkamk I would suggest to upgrade and test the application with the latest version

@devorgpl
Copy link

devorgpl commented Oct 16, 2023

Same error with "delete", OpenJDK 21

        <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
        <quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
        <quarkus.platform.version>3.4.3</quarkus.platform.version>
        <surefire-plugin.version>3.1.2</surefire-plugin.version>
        <compiler-plugin.version>3.11.0</compiler-plugin.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <assertj.version>3.22.0</assertj.version>

Steps to reproduce:
git clone https://github.com/quarkusio/quarkus-quickstarts && cd quarkus-quickstarts/hibernate-reactive-panache-quickstart

add more samples in import.sql

INSERT INTO fruit(id, name) VALUES (1, 'Cherry');
INSERT INTO fruit(id, name) VALUES (2, 'Apple');
INSERT INTO fruit(id, name) VALUES (3, 'Banana');
INSERT INTO fruit(id, name) VALUES (4, 'Banana1');
INSERT INTO fruit(id, name) VALUES (5, 'Banana2');
INSERT INTO fruit(id, name) VALUES (6, 'Banana3');
INSERT INTO fruit(id, name) VALUES (7, 'Banana4');
INSERT INTO fruit(id, name) VALUES (8, 'Banana5');
INSERT INTO fruit(id, name) VALUES (9, 'Banana6');
INSERT INTO fruit(id, name) VALUES (10, 'Banana7');
INSERT INTO fruit(id, name) VALUES (11, 'Banana8');
INSERT INTO fruit(id, name) VALUES (12, 'Banana9');
INSERT INTO fruit(id, name) VALUES (13, 'Banana11');
INSERT INTO fruit(id, name) VALUES (14, 'Banana12');
INSERT INTO fruit(id, name) VALUES (15, 'Banana14');
INSERT INTO fruit(id, name) VALUES (16, 'Banana15');
INSERT INTO fruit(id, name) VALUES (17, 'Banana16');
INSERT INTO fruit(id, name) VALUES (18, 'Banana17');
INSERT INTO fruit(id, name) VALUES (19, 'Banana88');
ALTER SEQUENCE fruit_seq RESTART WITH 20;

Start server:
mvn quarkus:dev

run test:

for i in {1..19}
 do
curl -X DELETE "http://localhost:8080/fruits/${i}"&
done

Result:

$ /bin/bash quarkus-quickstarts/hibernate-reactive-panache-quickstart/delete.sh
$ {"exceptionType":"org.hibernate.HibernateException","code":500,"error":"java.lang.IllegalStateException: HR000069: Detected use of the reactive Session from a different Thread than the one which was used to open the reactive Session - this suggests an invalid integration; original thread [138]: 'vert.x-eventloop-thread-3' current Thread [137]: 'vert.x-eventloop-thread-2'"}

and server exception:

Hibernate: 
    select
        f1_0.id,
        f1_0.name 
    from
        Fruit f1_0 
    where
        f1_0.id=$1

2023-10-16 04:18:18,103 ERROR [org.acm.hib.orm.pan.FruitResource] (vert.x-eventloop-thread-3) Failed to handle request: org.hibernate.HibernateException: java.lang.IllegalStateException: HR000069: Detected use of the reactive Session from a different Thread than the one which was used to open the reactive Session - this suggests an invalid integration; original thread [138]: 'vert.x-eventloop-thread-3' current Thread [137]: 'vert.x-eventloop-thread-2'
        at org.hibernate.reactive.session.impl.ReactiveExceptionConverter.convert(ReactiveExceptionConverter.java:28)
        at org.hibernate.reactive.session.impl.ReactiveSessionImpl.lambda$doFlush$27(ReactiveSessionImpl.java:994)
        at java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934)
        at java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:911)
        at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
        at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2179)
        at org.hibernate.reactive.util.async.impl.AsyncTrampoline$TrampolineInternal.unroll(AsyncTrampoline.java:131)
        at org.hibernate.reactive.util.async.impl.AsyncTrampoline$TrampolineInternal.lambda$unroll$0(AsyncTrampoline.java:126)
        at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863)
        at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841)
        at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
        at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2179)
        at org.hibernate.reactive.persister.entity.mutation.ReactiveDeleteCoordinator.complete(ReactiveDeleteCoordinator.java:198)
        at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863)
        at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841)
        at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
        at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2179)
        at io.vertx.core.Future.lambda$toCompletionStage$3(Future.java:536)
        at io.vertx.core.impl.future.FutureImpl$3.onSuccess(FutureImpl.java:141)
        at io.vertx.core.impl.future.FutureBase.emitSuccess(FutureBase.java:60)
        at io.vertx.core.impl.future.FutureImpl.tryComplete(FutureImpl.java:211)
        at io.vertx.core.impl.future.PromiseImpl.tryComplete(PromiseImpl.java:23)
        at io.vertx.sqlclient.impl.QueryResultBuilder.tryComplete(QueryResultBuilder.java:88)
        at io.vertx.sqlclient.impl.QueryResultBuilder.tryComplete(QueryResultBuilder.java:32)
        at io.vertx.core.Promise.complete(Promise.java:66)
        at io.vertx.core.Promise.handle(Promise.java:51)
        at io.vertx.core.Promise.handle(Promise.java:29)
        at io.vertx.core.impl.future.FutureImpl$3.onSuccess(FutureImpl.java:141)
        at io.vertx.core.impl.future.FutureBase.emitSuccess(FutureBase.java:60)
        at io.vertx.core.impl.future.FutureImpl.tryComplete(FutureImpl.java:211)
        at io.vertx.core.impl.future.PromiseImpl.tryComplete(PromiseImpl.java:23)
        at io.vertx.core.impl.future.PromiseImpl.onSuccess(PromiseImpl.java:49)
        at io.vertx.core.impl.future.PromiseImpl.handle(PromiseImpl.java:41)
        at io.vertx.sqlclient.impl.TransactionImpl.lambda$wrap$0(TransactionImpl.java:72)
        at io.vertx.core.impl.future.FutureImpl$3.onSuccess(FutureImpl.java:141)
        at io.vertx.core.impl.future.FutureBase.lambda$emitSuccess$0(FutureBase.java:54)
        at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:173)
        at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:166)
        at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:566)
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.lang.IllegalStateException: HR000069: Detected use of the reactive Session from a different Thread than the one which was used to open the reactive Session - this suggests an invalid integration; original thread [138]: 'vert.x-eventloop-thread-3' current Thread [137]: 'vert.x-eventloop-thread-2'
        at org.hibernate.reactive.common.InternalStateAssertions.assertCurrentThreadMatches(InternalStateAssertions.java:46)
        at org.hibernate.reactive.session.impl.ReactiveSessionImpl.threadCheck(ReactiveSessionImpl.java:183)
        at org.hibernate.reactive.session.impl.ReactiveSessionImpl.checkOpen(ReactiveSessionImpl.java:1670)
        at org.hibernate.internal.AbstractSharedSessionContract.checkOpenOrWaitingForAutoClose(AbstractSharedSessionContract.java:447)
        at org.hibernate.internal.SessionImpl.checkOpenOrWaitingForAutoClose(SessionImpl.java:616)
        at org.hibernate.internal.SessionImpl.getPersistenceContext(SessionImpl.java:1825)
        at org.hibernate.reactive.event.impl.AbstractReactiveFlushingEventListener.lambda$performExecutions$0(AbstractReactiveFlushingEventListener.java:65)
        at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863)
        at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841)
        ... 40 more

@devorgpl
Copy link

Exception is random.
This workaround seems to work:

@Entity
@Cacheable
@NamedQueries({
        @NamedQuery(name = "Fruit.deleteById", query = "delete from Fruit p where p.id = ?1")
})
public class Fruit extends PanacheEntity {
[...]
    public static Uni<Boolean> deleteById(Long id) {
        return delete("#Fruit.deleteById", id).map(t -> t > 0);
    }
}

@zivkovic
Copy link

I have the same problem. Simply performance testing the repository "deleteById" method, which is autogenerated by quarkus throws this error. If I replace the implementation with the code below, then delete works as it should (thanks @devorgpl, I have no idea how you managed to discover this). This tells me the problem seems to be in quarkus panache implementation itself. Debugging this is a real PITA.

override fun deleteById(id: UUID): Uni<Boolean> {
    return delete("id = ?1", id).map { result -> result > 0 }
}

@DavideD
Copy link
Contributor

DavideD commented Oct 30, 2023

I'm not sure why it fails, but using @WithTransaction seems to fix the issue:

    @DELETE
    @Path("{id}")
    @WithTransaction
    public Uni<Response> delete(Long id) {
        return Fruit.deleteById(id)
                .map(deleted -> deleted
                        ? Response.ok().status(NO_CONTENT).build()
                        : Response.ok().status(NOT_FOUND).build());
    }

I'm still looking into this though

@DavideD
Copy link
Contributor

DavideD commented Oct 30, 2023

Nevermind, using the annotation doesn't solve the issue

@DavideD
Copy link
Contributor

DavideD commented Oct 30, 2023

@mkouba I think we might need your help with this issue

@mkouba
Copy link
Contributor

mkouba commented Oct 31, 2023

@mkouba I think we might need your help with this issue

@DavideD I'm not sure I will be of any help here - the stack trace from the hibernate-reactive-panache-quickstart does not contain anything related to HR Panache. Am I missing somethig?

@DavideD
Copy link
Contributor

DavideD commented Oct 31, 2023

I don't think it's Panache, but it seems that the session is created in one thread and then used in another.
I was wondering if you might have some word of wisdom, or maybe there's an annotation that I'm not aware about that could help.

@mkouba
Copy link
Contributor

mkouba commented Oct 31, 2023

I don't think it's Panache, but it seems that the session is created in one thread and then used in another. I was wondering if you might have some word of wisdom, or maybe there's an annotation that I'm not aware about that could help.

I'm not aware of any annotation that could help here. It seems that the session is opened on the thread that handles the request, in this particular case on the thread that executed the FruitResource.delete() method. But for some reason the flush operation seems to be executed on a different thread...

@DavideD
Copy link
Contributor

DavideD commented Oct 31, 2023

I wonder if it's because the deleteById is split into a find and then a delete operation, instead of being a single one.
Anyway, I will continue looking.

@mkouba
Copy link
Contributor

mkouba commented Oct 31, 2023

I wonder if it's because the deleteById is split into a find and then a delete operation, instead of being a single one. Anyway, I will continue looking.

Well, it should not be a problem since the operations are executed within a single transaction, right?

@DavideD
Copy link
Contributor

DavideD commented Oct 31, 2023

Yes, it shouldn't. Unless we are missing something.

@DavidMachacek
Copy link

Same problem here
fun getAllPets(): Uni<List<PetDTO>> { logger.info { "operation=getAllPetsBegin, layer=service" } val criteriaBuilder = sessionFactory.criteriaBuilder val query = criteriaBuilder.createQuery(PetDTO::class.java) //for some reason, root query must be specified, even if not unused val root = query.from(PetDTO::class.java) return sessionFactory.withSession { session -> logger.info { "operation=getAllPetsBegin, layer=hibernate" } session.createQuery(query).resultList .onItem().ifNull().continueWith{listOf(PetDTO())} .onItem().call(session::flush) .also { logger.info { "operation=getAllPetsEnd, layer=hibernate, result=complete" } } }.also { logger.info { "operation=getAllPetsEnd, layer=service" } } }

Dependencies:
vertx-stack-depchain:4.1.8
hibernate-reactive-core:2.0.6.Final

ErrorStack:
2023-11-07T08:43:19.502Z INFO 1 --- [ntloop-thread-0] com.sgc.appd.vertxdemo.PetService : operation=getAllPetsEnd, layer=hibernate, result=complete [Hibernate] select p1_0.id,p1_0.name,p1_0.type from PetDTO p1_0 2023-11-07T08:43:19.504Z INFO 1 --- [ntloop-thread-0] com.sgc.appd.vertxdemo.PetHandlers : operation=getAllEnd, layer=handler [-- Mutiny had to drop the following exception --] Exception received by: io.smallrye.mutiny.infrastructure.Infrastructure.handleDroppedException(Infrastructure.java:295) io.smallrye.mutiny.CompositeException: Multiple exceptions caught: [Exception 0] java.lang.IllegalStateException: HR000069: Detected use of the reactive Session from a different Thread than the one which was used to open the reactive Session - this suggests an invalid integration; original thread [40]: 'vert.x-eventloop-thread-0' current Thread [47]: 'vert.x-eventloop-thread-1' [Exception 1] java.lang.IllegalStateException: HR000069: Detected use of the reactive Session from a different Thread than the one which was used to open the reactive Session - this suggests an invalid integration; original thread [40]: 'vert.x-eventloop-thread-0' current Thread [47]: 'vert.x-eventloop-thread-1' at io.smallrye.mutiny.groups.UniOnItemOrFailure.lambda$call$1(UniOnItemOrFailure.java:75) at io.smallrye.mutiny.operators.uni.UniOnItemOrFailureFlatMap$UniOnItemOrFailureFlatMapProcessor.performInnerSubscription(UniOnItemOrFailureFlatMap.java:86) at io.smallrye.mutiny.operators.uni.UniOnItemOrFailureFlatMap$UniOnItemOrFailureFlatMapProcessor.onFailure(UniOnItemOrFailureFlatMap.java:65) at io.smallrye.mutiny.operators.uni.UniOperatorProcessor.onFailure(UniOperatorProcessor.java:55) at io.smallrye.mutiny.helpers.EmptyUniSubscription.propagateFailureEvent(EmptyUniSubscription.java:40) at io.smallrye.mutiny.operators.uni.builders.UniCreateFromCompletionStage.subscribe(UniCreateFromCompletionStage.java:26) at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36) at io.smallrye.mutiny.operators.uni.UniRunSubscribeOn.lambda$subscribe$0(UniRunSubscribeOn.java:27) at org.hibernate.reactive.context.impl.VertxContext.execute(VertxContext.java:91) at io.smallrye.mutiny.operators.uni.UniRunSubscribeOn.subscribe(UniRunSubscribeOn.java:25) at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36) at io.smallrye.mutiny.operators.uni.UniOnItemOrFailureFlatMap.subscribe(UniOnItemOrFailureFlatMap.java:27) at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36) at io.smallrye.mutiny.operators.uni.UniOnItemOrFailureFlatMap$UniOnItemOrFailureFlatMapProcessor.performInnerSubscription(UniOnItemOrFailureFlatMap.java:99) at io.smallrye.mutiny.operators.uni.UniOnItemOrFailureFlatMap$UniOnItemOrFailureFlatMapProcessor.onFailure(UniOnItemOrFailureFlatMap.java:65) at io.smallrye.mutiny.operators.uni.UniOnItemOrFailureConsume$UniOnItemOrFailureConsumeProcessor.onFailure(UniOnItemOrFailureConsume.java:46) at io.smallrye.mutiny.operators.uni.UniOperatorProcessor.onFailure(UniOperatorProcessor.java:55) at io.smallrye.mutiny.operators.uni.UniOperatorProcessor.onFailure(UniOperatorProcessor.java:55) at io.smallrye.mutiny.operators.uni.UniOperatorProcessor.onFailure(UniOperatorProcessor.java:55) at io.smallrye.mutiny.operators.uni.UniOperatorProcessor.onFailure(UniOperatorProcessor.java:55) at io.smallrye.mutiny.operators.uni.builders.UniCreateFromCompletionStage$CompletionStageUniSubscription.forwardResult(UniCreateFromCompletionStage.java:58) at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863) at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841) at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2162) at org.hibernate.reactive.util.async.impl.AsyncTrampoline$TrampolineInternal.lambda$unroll$0(AsyncTrampoline.java:123) at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863) at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841) at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2147) at io.vertx.core.Future.lambda$toCompletionStage$2(Future.java:360) at io.vertx.core.impl.future.FutureImpl$3.onSuccess(FutureImpl.java:141) at io.vertx.core.impl.future.FutureBase.emitSuccess(FutureBase.java:60) at io.vertx.core.impl.future.FutureImpl.tryComplete(FutureImpl.java:211) at io.vertx.core.impl.future.PromiseImpl.tryComplete(PromiseImpl.java:23) at io.vertx.sqlclient.impl.QueryResultBuilder.tryComplete(QueryResultBuilder.java:102) at io.vertx.sqlclient.impl.QueryResultBuilder.tryComplete(QueryResultBuilder.java:35) at io.vertx.core.Promise.complete(Promise.java:66) at io.vertx.core.Promise.handle(Promise.java:51) at io.vertx.core.Promise.handle(Promise.java:29) at io.vertx.core.impl.future.FutureImpl$3.onSuccess(FutureImpl.java:141) at io.vertx.core.impl.future.FutureBase.emitSuccess(FutureBase.java:60) at io.vertx.core.impl.future.FutureImpl.tryComplete(FutureImpl.java:211) at io.vertx.core.impl.future.PromiseImpl.tryComplete(PromiseImpl.java:23) at io.vertx.core.impl.future.PromiseImpl.onSuccess(PromiseImpl.java:49) at io.vertx.core.impl.future.PromiseImpl.handle(PromiseImpl.java:41) at io.vertx.core.impl.future.PromiseImpl.handle(PromiseImpl.java:23) at io.vertx.sqlclient.impl.command.CommandResponse.fire(CommandResponse.java:46) at io.vertx.sqlclient.impl.SocketConnectionBase.handleMessage(SocketConnectionBase.java:287) at io.vertx.sqlclient.impl.SocketConnectionBase.lambda$init$0(SocketConnectionBase.java:99) at io.vertx.core.net.impl.NetSocketImpl.lambda$new$1(NetSocketImpl.java:97) at io.vertx.core.streams.impl.InboundBuffer.handleEvent(InboundBuffer.java:240) at io.vertx.core.streams.impl.InboundBuffer.write(InboundBuffer.java:130) at io.vertx.core.net.impl.NetSocketImpl.lambda$handleMessage$9(NetSocketImpl.java:390) at io.vertx.core.impl.EventLoopContext.emit(EventLoopContext.java:50) at io.vertx.core.impl.ContextImpl.emit(ContextImpl.java:274) at io.vertx.core.impl.EventLoopContext.emit(EventLoopContext.java:22) at io.vertx.core.net.impl.NetSocketImpl.handleMessage(NetSocketImpl.java:389) at io.vertx.core.net.impl.ConnectionBase.read(ConnectionBase.java:155) at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:154) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) at io.vertx.mssqlclient.impl.codec.TdsMessageEncoder.lambda$write$0(TdsMessageEncoder.java:63) at io.vertx.mssqlclient.impl.codec.MSSQLCommandCodec.complete(MSSQLCommandCodec.java:199) at io.vertx.mssqlclient.impl.codec.MSSQLCommandCodec.handleDecodingComplete(MSSQLCommandCodec.java:189) at io.vertx.mssqlclient.impl.codec.MSSQLCommandCodec.decode(MSSQLCommandCodec.java:83) at io.vertx.mssqlclient.impl.codec.TdsMessageDecoder.decodeMessage(TdsMessageDecoder.java:65) at io.vertx.mssqlclient.impl.codec.TdsMessageDecoder.channelRead(TdsMessageDecoder.java:43) at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1371) at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1234) at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1283) at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:507) at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:446) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:833) Suppressed: java.lang.IllegalStateException: HR000069: Detected use of the reactive Session from a different Thread than the one which was used to open the reactive Session - this suggests an invalid integration; original thread [40]: 'vert.x-eventloop-thread-0' current Thread [47]: 'vert.x-eventloop-thread-1' at org.hibernate.reactive.common.InternalStateAssertions.assertCurrentThreadMatches(InternalStateAssertions.java:46) at org.hibernate.reactive.session.impl.ReactiveSessionImpl.threadCheck(ReactiveSessionImpl.java:183) at org.hibernate.reactive.session.impl.ReactiveSessionImpl.checkOpen(ReactiveSessionImpl.java:1670) at org.hibernate.internal.AbstractSharedSessionContract.checkOpenOrWaitingForAutoClose(AbstractSharedSessionContract.java:447) at org.hibernate.internal.SessionImpl.checkOpenOrWaitingForAutoClose(SessionImpl.java:616) at org.hibernate.internal.SessionImpl.closeWithoutOpenChecks(SessionImpl.java:410) at org.hibernate.internal.SessionImpl.close(SessionImpl.java:397) at org.hibernate.reactive.session.impl.ReactiveSessionImpl.reactiveClose(ReactiveSessionImpl.java:1622) at io.smallrye.mutiny.operators.uni.builders.UniCreateFromCompletionStage.subscribe(UniCreateFromCompletionStage.java:24) ... 95 more Caused by: java.lang.IllegalStateException: HR000069: Detected use of the reactive Session from a different Thread than the one which was used to open the reactive Session - this suggests an invalid integration; original thread [40]: 'vert.x-eventloop-thread-0' current Thread [47]: 'vert.x-eventloop-thread-1' at org.hibernate.reactive.common.InternalStateAssertions.assertCurrentThreadMatches(InternalStateAssertions.java:46) at org.hibernate.reactive.session.impl.ReactiveSessionImpl.threadCheck(ReactiveSessionImpl.java:183) at org.hibernate.reactive.session.impl.ReactiveSessionImpl.checkOpen(ReactiveSessionImpl.java:1670) at org.hibernate.internal.AbstractSharedSessionContract.checkOpenOrWaitingForAutoClose(AbstractSharedSessionContract.java:447) at org.hibernate.internal.SessionImpl.checkOpenOrWaitingForAutoClose(SessionImpl.java:616) at org.hibernate.internal.SessionImpl.instantiate(SessionImpl.java:1464) at org.hibernate.sql.results.graph.entity.AbstractEntityInitializer.instantiateEntity(AbstractEntityInitializer.java:687) at org.hibernate.sql.results.graph.entity.AbstractEntityInitializer.resolveEntityInstance(AbstractEntityInitializer.java:680) at org.hibernate.sql.results.graph.entity.AbstractEntityInitializer.resolveInstance(AbstractEntityInitializer.java:646) at org.hibernate.sql.results.graph.entity.AbstractEntityInitializer.resolveEntityInstance(AbstractEntityInitializer.java:537) at org.hibernate.sql.results.graph.entity.AbstractEntityInitializer.resolveInstance(AbstractEntityInitializer.java:397) at org.hibernate.reactive.sql.results.graph.entity.ReactiveAbstractEntityInitializer.reactiveResolveInstance(ReactiveAbstractEntityInitializer.java:79) at org.hibernate.reactive.sql.results.internal.ReactiveInitializersList.lambda$resolveInstances$1(ReactiveInitializersList.java:86) at org.hibernate.reactive.util.impl.CompletionStages.lambda$loop$2(CompletionStages.java:178) at org.hibernate.reactive.util.impl.CompletionStages.lambda$loop$7(CompletionStages.java:417) at org.hibernate.reactive.util.impl.CompletionStages$ArrayLoop.next(CompletionStages.java:491) at org.hibernate.reactive.util.async.impl.AsyncTrampoline.lambda$asyncWhile$1(AsyncTrampoline.java:215) at org.hibernate.reactive.util.async.impl.AsyncTrampoline$TrampolineInternal.unroll(AsyncTrampoline.java:121) at org.hibernate.reactive.util.async.impl.AsyncTrampoline$TrampolineInternal.trampoline(AsyncTrampoline.java:102) at org.hibernate.reactive.util.async.impl.AsyncTrampoline.asyncWhile(AsyncTrampoline.java:197) at org.hibernate.reactive.util.async.impl.AsyncTrampoline.asyncWhile(AsyncTrampoline.java:215) at org.hibernate.reactive.util.impl.CompletionStages.loop(CompletionStages.java:418) at org.hibernate.reactive.util.impl.CompletionStages.loop(CompletionStages.java:389) at org.hibernate.reactive.util.impl.CompletionStages.loop(CompletionStages.java:178) at org.hibernate.reactive.sql.results.internal.ReactiveInitializersList.resolveInstances(ReactiveInitializersList.java:84) at org.hibernate.reactive.sql.results.internal.ReactiveStandardRowReader.coordinateInitializers(ReactiveStandardRowReader.java:125) at org.hibernate.reactive.sql.results.internal.ReactiveStandardRowReader.reactiveReadRow(ReactiveStandardRowReader.java:59) at org.hibernate.reactive.sql.results.spi.ReactiveListResultsConsumer.lambda$addToResultsSupplier$5(ReactiveListResultsConsumer.java:134) at org.hibernate.reactive.sql.results.spi.ReactiveListResultsConsumer.lambda$consume$1(ReactiveListResultsConsumer.java:108) at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1150) ... 73 more [------------------------------------------------] java.net.SocketException: Connection reset at java.base/sun.nio.ch.SocketChannelImpl.throwConnectionReset(SocketChannelImpl.java:394) at java.base/sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:426) at io.netty.buffer.PooledByteBuf.setBytes(PooledByteBuf.java:253) at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1132) at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:350) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:151) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:833)

@f4lco
Copy link

f4lco commented Aug 9, 2024

We do think that the bug is still relevant 2.5 years later, and might have caused / contributed to #41240 (comment).
With Quarkus 3.8.5, we get the same stack traces, and the proposed workarounds successfully mitigate the error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/hibernate-reactive Hibernate Reactive kind/bug Something isn't working
Projects
None yet
Development

No branches or pull requests