Why does @Value sometimes fail to inject properties?
@Value failing to inject properties is one of the most confusing Spring problems because it often fails silently or only in specific environments.
The reason is not “Spring is broken” — it’s always due to how and when property sources are loaded and how the bean is created.
Let’s go deep from internals → real-world failure patterns → professional fixes.
1. How @Value Actually Works (Internal Mechanism)
@Value is handled by:
PropertySourcesPlaceholderConfigurer
It runs during:
Bean definition post-processing phase
Not during normal runtime.



So if properties are not available at that exact phase, injection fails.
2. The 8 Most Common Reasons @Value Fails
2.1 Bean Created Before Property Loader
This is the #1 real-world cause.
Example:
@Bean
public MyService myService() {
return new MyService();
}
If MyService is created before:
@PropertySource("classpath:app.properties")
Then:
@Value("${timeout}")
private int timeout; // null / 0
Because property source not loaded yet.
2.2 Using @Value in Static Fields
@Value("${url}")
private static String url; // will always be null
Spring cannot inject into static fields.
Because:
Injection happens on instances, not classes.
2.3 Property Key Does Not Exist
@Value("${server.timeout}")
But in file:
server.timeOut=30
Case mismatch = not found.
Result:
Could not resolve placeholder
Or worse:
Injects empty string.
2.4 Profile-Specific Properties Not Loaded
spring.profiles.active=prod
But property exists in:
application-dev.properties
So in prod:
@Value("${api.key}") // fails
Because file not loaded.
2.5 Missing PropertySource
If not using Boot:
@Value("${app.name}")
But no:
@PropertySource("classpath:application.properties")
Then:
Spring has no idea where to look.
2.6 YAML Indentation / Structure Errors
app:
name: myApp
But:
@Value("${app.name}")
If indentation is wrong:
app:
name: myApp
port: 8080 # invalid
Entire block ignored.
2.7 Using @Value in @Configuration Constructor
@Configuration
public class Config {
public Config(@Value("${x}") String x) { }
}
Fails because:
@Configuration is processed before placeholders resolved.
This one is very subtle.
2.8 Wrong Environment / Docker / K8s
In containers:
ENV API_KEY=123
But using:
@Value("${api.key}")
Spring maps env vars:
API_KEY -> api.key
But only if:
relaxed binding is enabled
Misconfig = null.
3. Silent Failure Patterns (Most Dangerous)
| Pattern | Result |
|---|---|
| primitive int | injects 0 |
| boolean | injects false |
| String | injects “” |
| wrapper types | null |
No exception.
Bug detected in production.
4. Why @Value Is Considered Fragile
Because:
- No type safety
- No compile-time validation
- No grouping
- No documentation
It’s just:
String replacement at startup.
5. The Professional Replacement: @ConfigurationProperties
@ConfigurationProperties(prefix="app")
public class AppConfig {
private int timeout;
private String name;
}
Advantages:
- Strong typing
- Validated
- Fails fast
- IDE support
6. Debugging @Value Failures Like a Pro
Step 1 – Dump property sources
@Autowired
Environment env;
env.getPropertySources().forEach(System.out::println);
Step 2 – Check resolved value
env.getProperty("api.key");
If null → source not loaded.
7. Force Spring to Fail Fast
spring.main.fail-on-missing-placeholder=true
Now:
App crashes immediately if property missing.
No silent bugs.
8. Internal Ordering (Advanced)
Property resolution order:
- Command line args
- OS environment
- application.properties
- @PropertySource
- Default values
So:
--timeout=10
Overrides everything.
9. Interview-Grade Answer (For You, Nimai)
“@Value fails when the property source is not loaded at the time of placeholder resolution, such as with wrong profiles, missing PropertySource, static fields, early bean creation, or incorrect keys. Since it works during bean definition phase, timing and environment configuration are the main causes.”
Final Mental Model
Think of @Value as:
Text substitution during container bootstrap
If the text is not available at that moment, Spring cannot go back later.
Golden Rule
Use @Value only for:
- One-off constants
- Feature flags
For everything else:
Use
@ConfigurationPropertiesor you will debug ghosts in production.