Uploaded image for project: 'Red Hat build of Keycloak'
  1. Red Hat build of Keycloak
  2. RHBK-3226

NPE during loading user groups with concurrent deletion [GHI#40368]

XMLWordPrintable

    • False
    • Hide

      None

      Show
      None
    • False

      Before reporting an issue

      [x] I have read and understood the above terms for submitting issues, and I understand that my issue may be closed without action if I do not follow them.

      Area

      storage

      Describe the bug

      During fetching user groups we may face

      2025-06-10 11:14:57,477 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-472) Uncaught server error: java.lang.NullPointerException: Cannot invoke "org.keycloak.mod
      els.GroupModel.getSubGroupsCount()" because the return value of "org.keycloak.models.cache.infinispan.GroupAdapter.getGroupModel()" is null
      

      at org.keycloak.models.cache.infinispan.GroupAdapter.getSubGroupsCount(GroupAdapter.java:262)
      at org.keycloak.utils.GroupUtils.populateSubGroupCount(GroupUtils.java:82)
      at org.keycloak.utils.GroupUtils.lambda$populateGroupHierarchyFromSubGroups$2(GroupUtils.java:39)
      at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
      at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
      at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:395)
      at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:261)
      at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:261)
      at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510)
      at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
      at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
      at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
      at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
      at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
      at org.keycloak.utils.ClosingStream.forEach(ClosingStream.java:128)
      at org.keycloak.utils.GroupUtils.populateGroupHierarchyFromSubGroups(GroupUtils.java:31)
      at org.keycloak.services.resources.admin.GroupsResource.getGroups(GroupsResource.java:111)
      at org.keycloak.services.resources.admin.GroupsResource$quarkusrestinvoker$getGroups_09ec752a8eec558a48a704f25fc7f0c07e766424.invoke(Unknown Source)
      at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
      at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
      at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
      at io.quarkus.vertx.core.runtime.VertxCoreRecorder$15.runWith(VertxCoreRecorder.java:638)
      at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2675)
      at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2654)
      at org.jboss.threads.EnhancedQueueExecutor.runThreadBody(EnhancedQueueExecutor.java:1627)
      at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1594)
      at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:11)
      at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:11)
      at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
      at java.base/java.lang.Thread.run(Thread.java:1583)

      
      

      (after next occurrences it is shrinked to
      2025-06-10 11:38:07,175 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-521) Uncaught server error: java.lang.NullPointerException
      (without stack)

      Version

      26.2.5

      Regression

      [x] The issue is a regression

      Expected behavior

      No NPE during loading of user groups

      Actual behavior

      NPE is reproduced

      How to Reproduce?

      @Test
      void createMultiDeleteMultiReadMulti() {
      	// create multiple groups
      	List<String> groupUuuids = new ArrayList<>();
      	IntStream.range(0, 100).forEach(groupIndex -> {
      		GroupRepresentation group = new GroupRepresentation();
      		group.setName("Test Group " + groupIndex);
      		try (Response response = realmResource.groups().add(group)) {
      			boolean created = response.getStatusInfo().getFamily() == Response.Status.Family.SUCCESSFUL;
      			if (created) {
      				final String createdResourceLocation = response.getHeaderString("Location");
      				String groupUuid = StringUtils.substringAfterLast(createdResourceLocation, "/");
      				groupUuuids.add(groupUuid);
      			} else {
      				fail("Failed to create group: " + response.getStatusInfo().getReasonPhrase());
      			}
      		}
      	});
      
      	AtomicBoolean deletedAll = new AtomicBoolean(false);
      	List<Exception> caughtExceptions = new CopyOnWriteArrayList<>();
      	// read groups in a separate thread
      	new Thread(() -> {
      		while (!deletedAll.get()) {
      			try {
      				// just loading briefs
      				realmResource.groups().groups(null, 0, Integer.MAX_VALUE, true);
      			} catch (Exception e) {
      				caughtExceptions.add(e);
      			}
      		}
      	}).start();
      
      	// delete groups
      	groupUuuids.forEach(groupUuid -> {
      		realmResource.groups().group(groupUuid).remove();
      	});
      	deletedAll.set(true);
      
      	assertThat(caughtExceptions, Matchers.empty());
      }
      

      Anything else?

      1) The test is green on 22.0.5, No NPE
      2) No sub-groups are created by us, just top-level groups
      3) No user federation enabled, the groups are pure Keycloak internal groups

              Unassigned Unassigned
              pvlha Pavel Vlha
              Keycloak Core (shared)
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Created:
                Updated:
                Resolved: