spring-projects/spring-boot · error · RuntimeException
Failed to get dir mode from CopySpec
Error message
Failed to get dir mode from CopySpec
What it means
Thrown by BootArchiveSupport.getDirMode, which uses reflection to invoke CopySpec.getDirMode() on the legacy code path for Gradle versions below 8.3 (the caller checks GradleVersion 8.3 and uses getDirMode only when the modern getFilePermissions API is unavailable). Any reflection failure — NoSuchMethodException, IllegalAccessException, or InvocationTargetException — is wrapped in this RuntimeException.
Solutions
- Upgrade Gradle to 8.3 or later to use the modern permissions API and bypass reflection entirely.
- Remove or update any plugin that replaces the standard Gradle CopySpec implementation.
- If pinned to an old Gradle, downgrade the Spring Boot plugin to a version that supports that Gradle.
Example fix
// before: Gradle 7.x triggers reflective getDirMode // after: upgrade wrapper to 8.14+ distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
Defensive patterns
Strategy: validation
Validate before calling
// Gate on Gradle version before building boot archives.
if (GradleVersion.current().compareTo(GradleVersion.version("8.3")) < 0) {
throw new GradleException("Upgrade to Gradle 8.3+ to avoid reflective getDirMode.")
} Prevention
- Use Gradle 8.3+ (preferably 8.14+) via the wrapper.
- Avoid plugins that replace the default CopySpec implementation.
- Keep Gradle and Spring Boot plugin versions aligned.
When it happens
Trigger: Building a boot archive (bootJar/bootWar) on a Gradle version below 8.3 where the CopySpec implementation lacks a getDirMode() method, or the method exists but throws during invocation (e.g. because permissions are in an invalid state).
Common situations: Running on an old Gradle (< 8.3) where the reflective method signature differs. A third-party plugin replacing the default CopySpec. A Gradle version where getDirMode exists but returns unexpectedly. Combined with custom launchScripts or from() calls that mutate the CopySpec.
Related errors
- Failed to get file mode from CopySpec
- Failed to get mode from FileCopyDetails
- Failed to set file mode on CopySpec
- Failed to add to
- Failed to create
AI-assisted analysis of spring-projects/spring-boot@270dfe353f (2026-08-11).
Data as JSON: /api/errors/36c7b74ebae27dcc.
Report an issue: GitHub.
Appendix: source
Thrown at build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java:158
return (GradleVersion.current().compareTo(GradleVersion.version("8.3")) >= 0)
? asUnixNumeric(copySpec.getDirPermissions()) : getDirMode(copySpec);
}
private @Nullable Integer getUnixNumericFilePermissions(CopySpec copySpec) {
return (GradleVersion.current().compareTo(GradleVersion.version("8.3")) >= 0)
? asUnixNumeric(copySpec.getFilePermissions()) : getFileMode(copySpec);
}
private @Nullable Integer asUnixNumeric(Property<ConfigurableFilePermissions> permissions) {
return permissions.isPresent() ? permissions.get().toUnixNumeric() : null;
}
private @Nullable Integer getDirMode(CopySpec copySpec) {
try {
return (Integer) copySpec.getClass().getMethod("getDirMode").invoke(copySpec);
}
catch (Exception ex) {
throw new RuntimeException("Failed to get dir mode from CopySpec", ex);
}
}
private @Nullable Integer getFileMode(CopySpec copySpec) {
try {
return (Integer) copySpec.getClass().getMethod("getFileMode").invoke(copySpec);
}
catch (Exception ex) {
throw new RuntimeException("Failed to get file mode from CopySpec", ex);
}
}
private boolean isUsingDefaultLoader(Jar jar) {
return DEFAULT_LAUNCHER_CLASSES.contains(jar.getManifest().getAttributes().get("Main-Class"));
}
void requiresUnpack(String... patterns) {
this.requiresUnpack.include(patterns);View on GitHub (pinned to 270dfe353f)