quarkusio/quarkus · error · IllegalStateException

no blocking executor specified

Error message

no blocking executor specified

What it means

The manager executes blocking identity providers on the supplied Executor (blockingExecutor). If build() runs before an executor was set, blocking authentication would deadlock or run on the caller thread, so the builder throws IllegalStateException.

Source

Thrown at extensions/security/runtime/src/main/java/io/quarkus/security/runtime/QuarkusIdentityProviderManagerImpl.java:254

        /**
         * @return a new {@link QuarkusIdentityProviderManagerImpl}
         */
        public QuarkusIdentityProviderManagerImpl build() {
            built = true;
            if (!providers.containsKey(AnonymousAuthenticationRequest.class)) {
                throw new IllegalStateException(
                        "No AnonymousIdentityProvider registered. An instance of AnonymousIdentityProvider must be provided to allow the Anonymous identity to be created.");
            }
            for (List<IdentityProvider<?>> providers : providers.values()) {
                providers.sort(new Comparator<IdentityProvider<? extends AuthenticationRequest>>() {
                    @Override
                    public int compare(IdentityProvider o1, IdentityProvider o2) {
                        return Integer.compare(o2.priority(), o1.priority());
                    }
                });
            }
            if (blockingExecutor == null) {
                throw new IllegalStateException("no blocking executor specified");
            }
            augmentors.sort(new Comparator<SecurityIdentityAugmentor>() {
                @Override
                public int compare(SecurityIdentityAugmentor o1, SecurityIdentityAugmentor o2) {
                    return Integer.compare(o2.priority(), o1.priority());
                }
            });
            if (quarkusPermissionAugmentor != null) {
                // @PermissionChecker methods must always run with the final SecurityIdentity
                augmentors.add(quarkusPermissionAugmentor);
            }
            return new QuarkusIdentityProviderManagerImpl(this);
        }
    }

}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Call builder.blockingExecutor(executor) with a suitable executor (e.g. Quarkus's managed executor or Executors.newFixedThreadPool) before build().
  2. Prefer obtaining the manager via CDI injection rather than building it manually.
  3. In extensions, use the standard SecurityIdentityProxy/recorder wiring that supplies the executor automatically.

Example fix

// before
var m = b.addProvider(p).build(); // no executor
// after
var m = b.addProvider(p)
    .blockingExecutor(Executors.newFixedThreadPool(4))
    .build();
Defensive patterns

Strategy: validation

Validate before calling

Objects.requireNonNull(executor, "blocking executor required before build()");
builder.blockingExecutor(executor);
var m = builder.build();

Prevention

When it happens

Trigger: Calling build() without invoking builder.blockingExecutor(executor) — common in manually constructed managers in tests or custom extensions.

Common situations: Tests creating the builder directly; custom runtime wiring where the default executor supplier build step was bypassed.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/b73f9b66e2646d53. Report an issue: GitHub.