{"record":{"id":"36c7b74ebae27dcc","repo":"spring-projects/spring-boot","slug":"failed-to-get-dir-mode-from-copyspec","errorCode":null,"errorMessage":"Failed to get dir mode from CopySpec","messagePattern":"Failed to get dir mode from CopySpec","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java","lineNumber":158,"sourceCode":"\t\treturn (GradleVersion.current().compareTo(GradleVersion.version(\"8.3\")) >= 0)\n\t\t\t\t? asUnixNumeric(copySpec.getDirPermissions()) : getDirMode(copySpec);\n\t}\n\n\tprivate @Nullable Integer getUnixNumericFilePermissions(CopySpec copySpec) {\n\t\treturn (GradleVersion.current().compareTo(GradleVersion.version(\"8.3\")) >= 0)\n\t\t\t\t? asUnixNumeric(copySpec.getFilePermissions()) : getFileMode(copySpec);\n\t}\n\n\tprivate @Nullable Integer asUnixNumeric(Property<ConfigurableFilePermissions> permissions) {\n\t\treturn permissions.isPresent() ? permissions.get().toUnixNumeric() : null;\n\t}\n\n\tprivate @Nullable Integer getDirMode(CopySpec copySpec) {\n\t\ttry {\n\t\t\treturn (Integer) copySpec.getClass().getMethod(\"getDirMode\").invoke(copySpec);\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\tthrow new RuntimeException(\"Failed to get dir mode from CopySpec\", ex);\n\t\t}\n\t}\n\n\tprivate @Nullable Integer getFileMode(CopySpec copySpec) {\n\t\ttry {\n\t\t\treturn (Integer) copySpec.getClass().getMethod(\"getFileMode\").invoke(copySpec);\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\tthrow new RuntimeException(\"Failed to get file mode from CopySpec\", ex);\n\t\t}\n\t}\n\n\tprivate boolean isUsingDefaultLoader(Jar jar) {\n\t\treturn DEFAULT_LAUNCHER_CLASSES.contains(jar.getManifest().getAttributes().get(\"Main-Class\"));\n\t}\n\n\tvoid requiresUnpack(String... patterns) {\n\t\tthis.requiresUnpack.include(patterns);","sourceCodeStart":140,"sourceCodeEnd":176,"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/BootArchiveSupport.java#L140-L176","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before: Gradle 7.x triggers reflective getDirMode\n// after: upgrade wrapper to 8.14+\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.14.2-bin.zip","handlingStrategy":"validation","validationCode":"// Gate on Gradle version before building boot archives.\nif (GradleVersion.current().compareTo(GradleVersion.version(\"8.3\")) < 0) {\n    throw new GradleException(\"Upgrade to Gradle 8.3+ to avoid reflective getDirMode.\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["gradle","reflection","file-permissions","version-compat","boot-archive","copy-spec"],"backgroundTag":null,"analyzedSha":"270dfe353fb830fd69b823a8a859287ff103854b","analyzedAt":"2026-08-11T19:42:06.541Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}