quarkusio/quarkus · error · IllegalStateException

manager has already been built

Error message

manager has already been built

What it means

The QuarkusIdentityProviderManagerImpl.Builder is one-shot: after build() is called, its 'built' flag is set and any further addProvider(...) throws IllegalStateException. This prevents mutating the provider registry after the manager is in use.

Source

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

        Builder() {
        }

        private final Map<Class<? extends AuthenticationRequest>, List<IdentityProvider<? extends AuthenticationRequest>>> providers = new HashMap<>();
        private final List<SecurityIdentityAugmentor> augmentors = new ArrayList<>();
        private QuarkusPermissionSecurityIdentityAugmentor quarkusPermissionAugmentor = null;
        private BlockingSecurityExecutor blockingExecutor;
        private boolean built = false;

        /**
         * Adds an {@link IdentityProvider} implementation to this manager
         *
         * @param provider The provider
         * @return this builder
         */
        public Builder addProvider(IdentityProvider<? extends AuthenticationRequest> provider) {
            if (built) {
                throw new IllegalStateException("manager has already been built");
            }
            providers.computeIfAbsent(provider.getRequestType(), (a) -> new ArrayList<>()).add(provider);
            return this;
        }

        /**
         * Adds an augmentor that can modify the security identity that is provided by the identity store.
         *
         * @param augmentor The augmentor
         * @return this builder
         */
        public Builder addSecurityIdentityAugmentor(SecurityIdentityAugmentor augmentor) {
            if (augmentor instanceof QuarkusPermissionSecurityIdentityAugmentor quarkusPermissionAugmentor) {
                this.quarkusPermissionAugmentor = quarkusPermissionAugmentor;
            } else {
                augmentors.add(augmentor);
            }
            return this;

View on GitHub (pinned to e1c734241f)

Solutions

  1. Call all addProvider(...) invocations before build(); restructure initialization so provider registration completes first.
  2. Create a new Builder instance if you need a second manager with additional providers.
  3. Register providers at build time via an IdentityProvider build step instead of runtime mutation.

Example fix

// before
var m = b.build();
b.addProvider(new ExtraProvider()); // throws
// after
b.addProvider(new ExtraProvider());
var m = b.build();
Defensive patterns

Strategy: validation

Validate before calling

if (builtManagers.contains(builder)) throw new IllegalStateException("builder already used");
// or track in code: add all providers, then build, then discard builder

Prevention

When it happens

Trigger: Holding a reference to the Builder and calling addProvider after manager construction; dynamically registering providers at runtime (e.g. in a startup callback that runs after the manager bean is created).

Common situations: Attempting to add providers from @Startup/@PostConstruct code that runs after the manager bean was produced; unit tests reusing a builder across manager instances.

Related errors


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