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

  1. Upgrade Gradle to 8.3 or later to use the modern permissions API and bypass reflection entirely.
  2. Remove or update any plugin that replaces the standard Gradle CopySpec implementation.
  3. 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

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


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)