{"record":{"id":"6dbbda490bca7d0a","repo":"spring-projects/spring-boot","slug":"each-image-building-cache-can-be-configured-only-o-6dbbda","errorCode":null,"errorMessage":"Each image building cache can be configured only once","messagePattern":"Each image building cache can be configured only once","errorType":"exception","errorClass":"GradleException","httpStatus":null,"severity":"error","filePath":"build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/LocalCacheSpec.java","lineNumber":59,"sourceCode":"\n\tprivate @Nullable LocalCache cache;\n\n\t@Inject\n\tpublic LocalCacheSpec(ObjectFactory objectFactory) {\n\t\tthis.objectFactory = objectFactory;\n\t}\n\n\tpublic @Nullable LocalCache asCache() {\n\t\treturn this.cache;\n\t}\n\n\t/**\n\t * Configures a volume cache using the given {@code action}.\n\t * @param action the action\n\t */\n\tpublic void volume(Action<VolumeCacheSpec> action) {\n\t\tif (this.cache != null) {\n\t\t\tthrow new GradleException(\"Each image building cache can be configured only once\");\n\t\t}\n\t\tVolumeCacheSpec spec = this.objectFactory.newInstance(VolumeCacheSpec.class);\n\t\taction.execute(spec);\n\t\tthis.cache = Cache.volume(spec.getName().get());\n\t}\n\n\t/**\n\t * Configures a bind cache using the given {@code action}.\n\t * @param action the action\n\t */\n\tpublic void bind(Action<BindCacheSpec> action) {\n\t\tif (this.cache != null) {\n\t\t\tthrow new GradleException(\"Each image building cache can be configured only once\");\n\t\t}\n\t\tBindCacheSpec spec = this.objectFactory.newInstance(BindCacheSpec.class);\n\t\taction.execute(spec);\n\t\tthis.cache = Cache.bind(spec.getSource().get());\n\t}","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/spring-projects/spring-boot/blob/270dfe353fb830fd69b823a8a859287ff103854b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/LocalCacheSpec.java#L41-L77","documentation":"Thrown by LocalCacheSpec.volume when this.cache is already non-null. LocalCacheSpec is the local-cache counterpart to CacheSpec (which also supports image caches). Each LocalCacheSpec accepts exactly one cache configuration: either volume or bind. Calling volume() a second time, or calling it after bind(), throws.","triggerScenarios":"Calling cache.volume { } after already calling cache.volume { } or cache.bind { } on the same LocalCacheSpec instance in a bootBuildImage (or related) configuration.","commonSituations":"Duplicate cache blocks in the build script. Refactoring from one cache type to another without removing the old block. Misunderstanding that LocalCacheSpec supports only one cache.","solutions":["Keep exactly one cache configuration (volume or bind) per LocalCacheSpec.","Audit the build script for multiple cache { } sub-blocks and remove duplicates."],"exampleFix":"// before\ncache {\n    volume { name = \"vol\" }\n    bind { source = \"/tmp/cache\" }  // throws\n}\n// after\ncache {\n    volume { name = \"vol\" }\n}","handlingStrategy":"validation","validationCode":"// Ensure no prior cache is configured before calling volume().\nif (localCacheSpec.asCache() != null) {\n    throw new GradleException(\"Local cache already configured; cannot call volume().\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use exactly one of volume/bind per LocalCacheSpec.","Audit build scripts after refactoring cache configuration."],"tags":["gradle","validation","build-image","cache","configuration","mutually-exclusive","local-cache"],"backgroundTag":null,"analyzedSha":"270dfe353fb830fd69b823a8a859287ff103854b","analyzedAt":"2026-08-11T19:42:06.541Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}