Maven Resource Filtering with Spring Boot Could not resolve placeholder
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
This error usually appears when Maven resource filtering and Spring Boot placeholder resolution are mixed without a clear boundary. Maven substitutes tokens at build time. Spring resolves placeholders at runtime from properties, environment variables, profiles, and command-line overrides. If the same syntax is used for both, unresolved values often slip into the packaged application and fail only when the app starts.
Build-Time Filtering and Runtime Resolution Are Different Steps
The first thing to keep straight is when each tool runs.
- Maven filtering happens while the artifact is being built.
- Spring resolves placeholders when the application is already running.
If a value should vary per deployment, it usually belongs to Spring runtime configuration. If it should be baked into the artifact, it may belong to Maven filtering.
Problems start when both systems try to interpret the same placeholder syntax.
Configure Maven Filtering Explicitly
A typical Maven setup enables filtering for text resources but excludes binary files.
Filtering binary files is a classic mistake because it corrupts them. That is why excludes matter.
Avoid Delimiter Collisions with Spring
Spring property placeholders commonly use syntax such as ${app.name}. Maven filtering can also use placeholder syntax, which creates collisions if both systems look for the same delimiters.
A practical fix is to change Maven delimiters to something distinct, such as @...@.
Then the properties file becomes much clearer.
Now Maven handles only @...@, while Spring keeps ${...} for runtime resolution.
Use Maven Profiles Only for True Build Differences
If you build different artifacts for different environments, Maven profiles can feed filtered values.
And then:
With:
If the profile is not activated, the placeholder may remain unresolved in the packaged resource. That is a build problem, not a Spring problem.
Debug the Packaged Artifact First
When startup says a placeholder could not be resolved, inspect the file inside the built JAR. That tells you whether filtering happened at all.
If the Maven token is still present, fix the build configuration. If the Maven token is resolved but Spring’s runtime placeholder still fails, the problem is now in runtime configuration or property-source order.
Running Spring Boot with debug output can also help confirm which property sources were loaded.
Keep Secrets Out of Build-Time Filtering
A common anti-pattern is filtering secrets into the artifact during Maven build. That makes the build environment own deployment secrets and usually creates unnecessary risk.
Build metadata is a good fit for filtering. Secrets and environment-specific operational settings are usually better handled by Spring at runtime from environment variables, secret stores, or deployment systems.
Common Pitfalls
- Using the same delimiter style for Maven filtering and Spring runtime placeholders.
- Filtering binary resources and corrupting them.
- Forgetting to activate the Maven profile that provides a filtered value.
- Baking deployment-specific secrets into the artifact at build time.
- Debugging Spring first when the unresolved token is actually still sitting in the packaged resource.
Summary
- Maven filtering and Spring placeholder resolution happen at different stages.
- Use distinct delimiters to avoid collisions between build-time and runtime substitution.
- Filter only text resources that truly need build-time values.
- Inspect the packaged resource to separate build problems from runtime configuration problems.
- Keep build metadata and runtime secrets clearly separated.

