spring-projects/spring-boot · error · GradleException
Each image building cache can be configured only once
Error message
Each image building cache can be configured only once
What it means
Thrown by CacheSpec.volume() when the build cache has already been configured (this.cache != null). A CacheSpec models a single cache; volume/bind/image are mutually exclusive and each can be set at most once. Raised as GradleException.
Source
Thrown at build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/CacheSpec.java:59
private @Nullable Cache cache;
@Inject
public CacheSpec(ObjectFactory objectFactory) {
this.objectFactory = objectFactory;
}
public @Nullable Cache asCache() {
return this.cache;
}
/**
* Configures a volume cache using the given {@code action}.
* @param action the action
*/
public void volume(Action<VolumeCacheSpec> action) {
if (this.cache != null) {
throw new GradleException("Each image building cache can be configured only once");
}
VolumeCacheSpec spec = this.objectFactory.newInstance(VolumeCacheSpec.class);
action.execute(spec);
this.cache = Cache.volume(spec.getName().get());
}
/**
* Configures a bind cache using the given {@code action}.
* @param action the action
*/
public void bind(Action<BindCacheSpec> action) {
if (this.cache != null) {
throw new GradleException("Each image building cache can be configured only once");
}
BindCacheSpec spec = this.objectFactory.newInstance(BindCacheSpec.class);
action.execute(spec);
this.cache = Cache.bind(spec.getSource().get());
}View on GitHub (pinned to 5b2dbdbb8b)
Solutions
- Configure the build cache exactly once with a single call: buildCache { volume { name = 'my-cache' } }.
- Remove duplicate buildCache {} blocks contributed by other applied scripts/plugins.
- If you need to switch cache type, delete the previous block first — do not stack them.
- Search the build for 'buildCache'/'volume {' to find all contributors.
Example fix
// before: cache configured twice
bootBuildImage {
buildCache { volume { name = 'cache-a' } }
buildCache { volume { name = 'cache-b' } } // throws
}
// after: single configuration
bootBuildImage {
buildCache { volume { name = 'cache-a' } }
}
Defensive patterns
Strategy: validation
Validate before calling
// Track cache configuration count to prevent double-config
var cacheConfigured = false
fun configureVolume(name: String) {
check(!cacheConfigured) { "Build cache already configured" }
cacheConfigured = true
// ... buildCache { volume { this.name = name } }
}
Prevention
- Centralize cache configuration in a single place (one buildCache block).
- Review applied convention plugins/init scripts for additional buildCache calls.
- Never migrate cache types by stacking blocks; replace the prior one.
When it happens
Trigger: Calling buildCache { volume { } } twice, or calling buildCache { volume {...} } after buildCache { bind {...} } (or image {...}) — the second call sees this.cache already set and throws at line 59.
Common situations: Copy-pasting cache config blocks; a shared plugin/Convention applying cache config that the build script also sets; migrating from volume to bind cache without removing the old block.
Related errors
- Each image building cache can be configured only once
- Invalid Docker configuration, either context or host can be
- Invalid value for option '--environment'. Expected 'NAME=VAL
- Invalid Docker {} registry configuration, either token or us
- Main class name has not been configured and it could not be
AI-assisted analysis of spring-projects/spring-boot@5b2dbdbb8b (2026-08-04).
Data as JSON: /data/errors/fadfe1925ed17157.json.
Report an issue: GitHub.