Fixing Spring Boot Error “The Elements Were Left Unbound”
Spring Boot provides a flexible way to manage application configuration using external property files. However, when these properties are bound to Java classes using @ConfigurationProperties, incorrect mappings can sometimes lead to startup errors. In this article, let us delve into understanding the Spring Boot exception “The Elements Were Left Unbound”, reproduce the error with a practical example, and explore how to resolve it effectively.
1. Understanding Configuration Binding in Spring Boot
Spring Boot provides a powerful configuration mechanism that allows developers to externalize application settings instead of hardcoding them directly inside the application code. These configuration values are typically defined in files such as application.properties or application.yml, which are loaded automatically when the application starts.
Externalizing configuration offers several advantages. It allows applications to be easily configured for different environments such as development, testing, and production without modifying the source code. For example, database URLs, API keys, mail server settings, and caching configurations can all be maintained outside the codebase and adjusted depending on the deployment environment.
In Spring Boot, these configuration values can be mapped to strongly typed Java classes using the @ConfigurationProperties annotation. This approach provides a clean and maintainable way to access configuration values throughout the application. Instead of repeatedly reading values using @Value, developers can bind related properties to a dedicated configuration class and inject it wherever needed.
Spring Boot automatically performs this binding process during application startup. It reads the configuration file, identifies the properties that match a specified prefix, and attempts to bind them to fields in the corresponding configuration class.
However, during this binding process, developers may sometimes encounter the exception message The elements were left unbound. This error occurs when Spring Boot detects configuration properties in the configuration file but fails to bind them to the fields of the class annotated with @ConfigurationProperties.
This situation usually arises due to issues such as:
- Mismatch between property names and Java field names
- Incorrect or missing prefix configuration
- Missing getters and setters in the configuration class
- The configuration class not being properly registered as a Spring bean
When such mismatches occur, Spring Boot cannot map the configuration values to the target object, and it reports those properties as unbound elements.
In the following sections, we will reproduce this exception using a simple Spring Boot example, examine the exact error output, understand why the problem occurs, and finally implement the correct solution to resolve it.
1.1 Meaning of the “The Elements Were Left Unbound” Error
The message The elements were left unbound indicates that Spring Boot has discovered configuration properties in the configuration file but could not associate them with any fields inside the class annotated with @ConfigurationProperties.
During application startup, Spring Boot’s property binding mechanism scans the configuration files and attempts to map property keys to fields in the target configuration class based on the specified prefix. If a property key exists but no matching field is found, Spring Boot marks that property as unbound.
For example, if the configuration file contains the following property:
mail.server.host=smtp.gmail.com
Spring Boot expects to find a corresponding field such as:
private String host;
inside the configuration class annotated with @ConfigurationProperties(prefix = "mail.server").
If the field name differs significantly—for example hostName instead of host—Spring Boot may fail to bind the property. When multiple such mismatches occur, the framework reports them in the startup logs with a message indicating that certain elements were left unbound.
Understanding this error is important because it usually points to inconsistencies between the configuration file and the structure of the configuration class. Once the naming mismatch or registration issue is corrected, Spring Boot can successfully bind the configuration values and the application starts without errors.
2. Reproducing the “The Elements Were Left Unbound” Exception
In this section, we will reproduce the scenario that leads to the The elements were left unbound exception in a Spring Boot application. The issue typically occurs when Spring Boot attempts to bind configuration properties from application.properties to a class annotated with @ConfigurationProperties, but the field names inside the class do not match the property keys defined in the configuration file.
Spring Boot’s property binding mechanism relies on mapping configuration keys to Java fields using a relaxed binding strategy. However, if the field names differ significantly from the property names, Spring Boot may fail to bind those properties and will report them as unbound elements.
2.1 Defining Properties in application.properties
Below is the configuration defined in the src/main/resources/application.properties file.
mail.server.host=smtp.gmail.com mail.server.port=587 mail.server.username=test@gmail.com
These properties define the configuration required to connect to a mail server. The prefix mail.server groups the configuration properties logically and allows them to be mapped to a configuration class using the same prefix.
In a typical Spring Boot application, these properties would be bound to a Java class using the @ConfigurationProperties annotation.
Now we attempt to bind these properties to a configuration class.
2.2 Creating the Configuration Properties Class
Below is the configuration class that attempts to map the properties from application.properties.
package com.example.demo.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "mail.server")
public class MailProperties {
private String hostName;
private int portNumber;
private String username;
public String getHostName() {
return hostName;
}
public void setHostName(String hostName) {
this.hostName = hostName;
}
public int getPortNumber() {
return portNumber;
}
public void setPortNumber(int portNumber) {
this.portNumber = portNumber;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
The class above is annotated with @ConfigurationProperties with the prefix mail.server. This means Spring Boot will try to map the following properties:
mail.server.hostmail.server.portmail.server.username
to the fields inside the MailProperties class.
However, there is a subtle issue here. The fields in the class are named hostName and portNumber, while the configuration properties are named host and port. Because of this mismatch, Spring Boot cannot correctly bind the properties to the fields.
Although the username field matches correctly, the other two properties remain unbound.
2.3 Spring Boot Application Entry Point
The following is the main class used to start the Spring Boot application.
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
When the application starts, Spring Boot initializes the application context and attempts to bind the configuration properties defined in application.properties to the MailProperties class.
During this process, Spring Boot’s property binding system analyzes the prefix mail.server and tries to match each configuration key to the corresponding fields inside the configuration class.
2.4 Exception Output During Application Startup
Since the field names do not match the property names, Spring Boot fails to bind some of the configuration properties. As a result, the following exception is thrown during application startup.
Binding to target org.springframework.boot.context.properties.bind.BindException Reason: The elements [mail.server.host, mail.server.port] were left unbound
This error message indicates that Spring Boot detected the properties mail.server.host and mail.server.port in the configuration file, but it could not find matching fields inside the MailProperties class to bind them.
Therefore, Spring Boot reports these configuration entries as unbound elements, which ultimately results in the startup exception.
3. Fixing the Unbound Configuration Properties
To resolve the issue, we must ensure that the configuration properties defined in application.properties match the field names inside the @ConfigurationProperties class. Spring Boot’s property binding mechanism relies on mapping configuration keys to Java fields. If the names align correctly, Spring Boot can automatically bind those values during application startup.
In our previous example, the properties mail.server.host and mail.server.port could not be bound because the configuration class contained fields named hostName and portNumber. Since these names did not match the property keys, Spring Boot reported them as unbound elements.
To fix this problem, we simply update the configuration class so that the field names correspond directly to the property names.
3.1 Corrected Configuration Properties Class
Below is the corrected version of the configuration class. Notice that the fields are now named host and port, which match the property names defined in the configuration file.
package com.example.demo.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "mail.server")
public class MailProperties {
private String host;
private int port;
private String username;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
With this change, Spring Boot can successfully bind the following properties:
mail.server.host→hostmail.server.port→portmail.server.username→username
Because the property keys and field names now match, the binding process completes successfully.
3.2 Accessing Properties in a Service Class
Next, we create a simple service class that injects the MailProperties configuration object and prints the bound values. This demonstrates that the configuration properties are correctly mapped.
@Service
public class MailService {
private final MailProperties mailProperties;
public MailService(MailProperties mailProperties) {
this.mailProperties = mailProperties;
}
public void printConfig() {
System.out.println("Host: " + mailProperties.getHost());
System.out.println("Port: " + mailProperties.getPort());
System.out.println("Username: " + mailProperties.getUsername());
}
}
Here, the MailProperties object is injected by Spring using dependency injection. Since Spring Boot has already bound the configuration values to this object, the service can directly access them using the getter methods.
3.3 Verifying the Binding Using CommandLineRunner
To verify that the properties are correctly bound when the application starts, we create a simple CommandLineRunner. This runner executes automatically after the application context has been initialized.
@Component
public class StartupRunner implements CommandLineRunner {
private final MailService mailService;
public StartupRunner(MailService mailService) {
this.mailService = mailService;
}
@Override
public void run(String... args) {
mailService.printConfig();
}
}
When the application starts, this runner invokes the service method that prints the configuration values to the console.
3.4 Successful Application Output
After fixing the configuration class, the application starts successfully and the configuration values are properly bound. The following output appears in the console.
Host: smtp.gmail.com Port: 587 Username: test@gmail.com
This confirms that Spring Boot successfully mapped the properties defined in application.properties to the fields of the
MailProperties class.
By ensuring that property names match the corresponding Java fields and that the configuration class is properly registered as a Spring bean, we can avoid the The elements were left unbound exception and ensure smooth property binding in Spring Boot applications.
4. Conclusion
The Spring Boot exception The elements were left unbound usually occurs when configuration properties cannot be mapped to fields inside a @ConfigurationProperties class. The most common reason is a mismatch between property names and Java field names. Ensuring that property keys match the field names and that the configuration class is properly registered as a Spring bean resolves this issue and allows Spring Boot to bind the configuration values successfully.




