spring-projects/spring-security · error · IllegalStateException
This object has not been built
Error message
This object has not been built
What it means
AbstractSecurityBuilder.getObject() throws IllegalStateException('This object has not been built') when queried before build() has run, because the 'building' flag is still false and this.object is unset. getObject() only returns the product of a completed build.
Source
Thrown at config/src/main/java/org/springframework/security/config/annotation/AbstractSecurityBuilder.java:51
private O object;
@Override
public final O build() {
if (this.building.compareAndSet(false, true)) {
this.object = doBuild();
return this.object;
}
throw new AlreadyBuiltException("This object has already been built");
}
/**
* Gets the object that was built. If it has not been built yet an Exception is
* thrown.
* @return the Object that was built
*/
public final O getObject() {
if (!this.building.get()) {
throw new IllegalStateException("This object has not been built");
}
return this.object;
}
/**
* Subclasses should implement this to perform the build.
* @return the object that should be returned by {@link SecurityBuilder#build()}.
* @throws Exception if an error occurs
*/
protected abstract O doBuild();
}
View on GitHub (pinned to 96852e8860)
Solutions
- Call build() before getObject(), or prefer getObject() only after the build phase has completed.
- Obtain the built object directly as a @Bean (e.g. declare AuthenticationManager as a bean) instead of pulling it from a builder.
- Restructure initialization order with @DependsOn or make the consumer lazily fetch the object at first use.
- If you control the builder subclass, ensure doBuild() is invoked before exposing getObject().
Example fix
// before AuthenticationManager am = builder.getObject(); // may not be built yet // after AuthenticationManager am = builder.build(); // ensures built before retrieval
Defensive patterns
Strategy: type-guard
Validate before calling
if (builder instanceof AbstractSecurityBuilder<?> b && !isBuilt(b)) {
b.build(); // build before getObject
} Try / catch
try {
object = builder.getObject();
} catch (IllegalStateException e) {
object = builder.build(); // lazily build on first access
} Prevention
- Establish a clear build-before-use order in initialization
- Expose built objects as beans rather than via builder.getObject()
- Use @DependsOn to enforce security config runs first
- Never call getObject() from constructors of earlier-initialized beans
When it happens
Trigger: Calling getObject() before build(), e.g. reading the built AuthenticationManager/SecurityFilterChain from a builder field during bean construction before the security configuration has been applied.
Common situations: Injecting the builder and calling getObject() in a @Bean method that runs earlier than the security configuration; accessing the object in a constructor of a bean initialized before security setup; forgetting to call build() entirely in custom builder code.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- This object has already been built
- Cannot apply {configurer} to already built object
- This has already been built with the following stacktrace. {
- Cannot configure both a CorsConfigurationSource and a PreFli
- Headers security is enabled, but no headers will be added. E
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/c72f16cb52162d52.
Report an issue: GitHub.