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 LocalCacheSpec.volume() when the local cache (buildWorkspace or launchCache) has already been configured (this.cache != null). volume and bind are mutually exclusive on a LocalCacheSpec; the second call throws GradleException at line 59.

Source

Thrown at build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/LocalCacheSpec.java:59

	private @Nullable LocalCache cache;

	@Inject
	public LocalCacheSpec(ObjectFactory objectFactory) {
		this.objectFactory = objectFactory;
	}

	public @Nullable LocalCache 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

  1. Configure buildWorkspace (or launchCache) with exactly one of volume/bind.
  2. Remove the prior block before switching cache type.
  3. Search the build (and applied init scripts) for buildWorkspace/launchCache to locate duplicates.

Example fix

// before: bind then volume on the same workspace
bootBuildImage {
    buildWorkspace { bind { source = '/tmp/ws' } }
    buildWorkspace { volume { name = 'ws-vol' } } // throws
}
// after: single workspace cache
bootBuildImage {
    buildWorkspace { volume { name = 'ws-vol' } }
}
Defensive patterns

Strategy: validation

Validate before calling

var localCacheConfigured = false
fun configureWorkspaceVolume(name: String) {
    check(!localCacheConfigured) { "buildWorkspace cache already configured" }
    localCacheConfigured = true
    // ... buildWorkspace { volume { this.name = name } }
}

Prevention

When it happens

Trigger: Calling buildWorkspace { volume { name = 'ws-vol' } } after buildWorkspace { bind {...} }, or calling volume twice — the second invocation sees this.cache already set.

Common situations: Applying both a bind and volume config to the same buildWorkspace/launchCache; copy-paste during migration between strategies; convention plugin plus local override.

Related errors


AI-assisted analysis of spring-projects/spring-boot@5b2dbdbb8b (2026-08-04). Data as JSON: /data/errors/6dbbda490bca7d0a.json. Report an issue: GitHub.