spring-projects/spring-boot · error · RuntimeException

Failed to get mode from FileCopyDetails

Error message

Failed to get mode from FileCopyDetails

What it means

Thrown by BootZipCopyAction's getMode, which reflectively invokes FileCopyDetails.getMode() on the legacy path for Gradude versions below 8.3 (the caller checks GradleVersion 8.3 and uses details.getPermissions().toUnixNumeric() on modern Gradle, falling back to getMode otherwise). Any reflection exception — NoSuchMethodException, IllegalAccessException, InvocationTargetException — is wrapped in a RuntimeException.

Solutions

  1. Upgrade Gradle to 8.3+ so the modern getPermissions().toUnixNumeric() path is used.
  2. Remove any plugin that replaces FileCopyDetails implementations.
  3. If pinned to old Gradle, downgrade the Spring Boot plugin to a compatible version.

Example fix

// before: Gradle 7.x uses reflective getMode
// after: upgrade wrapper
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
Defensive patterns

Strategy: validation

Validate before calling

// Gate on Gradle 8.3+ to use the modern permissions API.
if (GradleVersion.current().compareTo(GradleVersion.version("8.3")) < 0) {
    throw new GradleException("Upgrade to Gradle 8.3+ to avoid reflective getMode.")
}

Prevention

When it happens

Trigger: Building a boot archive on Gradle < 8.3 where FileCopyDetails lacks a getMode() method or the method throws during invocation. The modern path (details.getPermissions().toUnixNumeric()) is only taken on 8.3+.

Common situations: Running on an old Gradle version (< 8.3). A custom FileCopyDetails implementation that hides getMode(). Co-occurs with errors [5] and [6] as part of the same legacy-permissions reflection cluster.

Related errors


AI-assisted analysis of spring-projects/spring-boot@270dfe353f (2026-08-11). Data as JSON: /api/errors/a92f5afc04e2fbd9. Report an issue: GitHub.

Appendix: source

Thrown at build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java:485

			return (BootZipCopyAction.this.dirMode != null) ? BootZipCopyAction.this.dirMode : getPermissions(details);
		}

		private int getFileMode(FileCopyDetails details) {
			return (BootZipCopyAction.this.fileMode != null) ? BootZipCopyAction.this.fileMode
					: getPermissions(details);
		}

		private int getPermissions(FileCopyDetails details) {
			return (GradleVersion.current().compareTo(GradleVersion.version("8.3")) >= 0)
					? details.getPermissions().toUnixNumeric() : getMode(details);
		}

		private int getMode(FileCopyDetails details) {
			try {
				return (int) details.getClass().getMethod("getMode").invoke(details);
			}
			catch (Exception ex) {
				throw new RuntimeException("Failed to get mode from FileCopyDetails", ex);
			}
		}

	}

	/**
	 * Callback interface used to customize a {@link ZipArchiveEntry}.
	 */
	@FunctionalInterface
	private interface ZipEntryCustomizer {

		ZipEntryCustomizer NONE = (entry) -> {
		};

		/**
		 * Customize the entry.
		 * @param entry the entry to customize
		 * @throws IOException on IO error

View on GitHub (pinned to 270dfe353f)