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() when reflective invocation of CopySpec.getDirMode() fails. This reflection path is only used on Gradle < 8.3 (the dirPermissions API is used on 8.3+). Since the plugin requires Gradle 8.14+, this code path is unreachable in supported setups; encountering it means an unsupported Gradle or a non-standard CopySpec during bootJar/bootWar archive creation.

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 5b2dbdbb8b)

Solutions

  1. Upgrade Gradle to 8.14 or later so getDirPermissions().toUnixNumeric() is used instead.
  2. Verify GradleVersion.current() is not being spoofed by a malformed gradle-runtime.
  3. Ensure any custom CopySpec passed into bootJar/bootWar is a standard Gradle implementation.

Example fix

// gradle/wrapper/gradle-wrapper.properties
// before:
//   distributionUrl=...gradle-8.2-bin.zip
// after:
//   distributionUrl=...gradle-8.14-bin.zip
Defensive patterns

Strategy: validation

Validate before calling

import org.gradle.util.GradleVersion
require(GradleVersion.current() >= GradleVersion.version("8.3")) {
    "Boot archive file/dir mode requires Gradle 8.3+ (use 8.14+)"
}

Prevention

When it happens

Trigger: getUnixNumericDirPermissions() routes to getDirMode() only when GradleVersion.current() < 8.3; the reflective getMethod("getDirMode").invoke(copySpec) throws, wrapped as RuntimeException at line 158.

Common situations: Running an unsupported old Gradle; a custom CopySpec injected into the boot archive that lacks getDirMode; JVM module restrictions blocking reflection on Gradle internals.

Related errors


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