spring-projects/spring-boot · error · GradleException

Failed to read

Error message

Failed to read '{}'

What it means

Thrown by ApplicationPluginAction.loadResource when an IOException occurs while reading a bundled classpath resource (e.g. a default start-script template) character-by-character into a StringWriter. The resource was located successfully (getResourceAsStream returned non-null, otherwise Assert.state would fire first), but the read loop itself failed partway. This is an internal plugin resource read, not a user file.

Solutions

  1. Clean and refresh the Gradle dependencies: run 'gradle --refresh-dependencies' to re-download a non-corrupt spring-boot-gradle-plugin JAR.
  2. Clear the Gradle caches for the plugin: remove ~/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-gradle-plugin and re-resolve.
  3. Verify the plugin JAR is not being shadowed or modified by a custom ClassLoader or fat-JAR packaging in the build.
  4. Check for filesystem-level issues (disk full, NFS hiccup) if the error appears intermittently.
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check that the resource exists and is openable before the read loop.
// Note: this guards resource presence, not read-time I/O failures.
try (var probe = getClass().getResourceAsStream(name)) {
    if (probe == null) {
        throw new IllegalStateException("Resource not found: " + name);
    }
} catch (IOException ex) {
    // resource unreadable even for a probe — abort early
}

Try / catch

// Recommended: catch GradleException around task execution and surface the cause.
try {
    project.getTasks().named("startScripts").get().getActions().forEach(a -> a.execute(task));
} catch (GradleException ex) {
    if (ex.getMessage() != null && ex.getMessage().startsWith("Failed to read '")) {
    //     handle corrupted plugin resource — refresh dependencies
        throw new GradleException("Plugin resource unreadable. Run 'gradle --refresh-dependencies'.", ex);
    }
    throw ex;
}

Prevention

When it happens

Trigger: Calling any Gradle task that triggers ApplicationPluginAction configuration (e.g. startScripts, installDist) when the JVM experiences an I/O interruption while reading the plugin's own bundled resource. The try-with-resources InputStreamReader.read(buffer) throws IOException inside the while loop.

Common situations: A corrupted or truncated plugin JAR (resource present in the index but unreadable), a custom ClassLoader that returns a broken stream, JVM running low on file descriptors, or the plugin JAR being replaced/modified while Gradle is still running. Extremely rare in normal operation since the resource is packaged inside the plugin itself.

Related errors


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

Appendix: source

Thrown at build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/ApplicationPluginAction.java:125

	}

	@Override
	public Class<? extends Plugin<Project>> getPluginClass() {
		return ApplicationPlugin.class;
	}

	private String loadResource(String name) {
		try (InputStreamReader reader = new InputStreamReader(getResourceAsStream(name))) {
			char[] buffer = new char[4096];
			int read;
			StringWriter writer = new StringWriter();
			while ((read = reader.read(buffer)) > 0) {
				writer.write(buffer, 0, read);
			}
			return writer.toString();
		}
		catch (IOException ex) {
			throw new GradleException("Failed to read '" + name + "'", ex);
		}
	}

	private InputStream getResourceAsStream(String name) {
		InputStream stream = getClass().getResourceAsStream(name);
		Assert.state(stream != null, "Resource '%s' not found'".formatted(name));
		return stream;
	}

	private void configureFilePermissions(CopySpec copySpec, int mode) {
		if (GradleVersion.current().compareTo(GradleVersion.version("8.3")) >= 0) {
			copySpec.filePermissions((filePermissions) -> filePermissions.unix(Integer.toString(mode, 8)));
		}
		else {
			configureFileMode(copySpec, mode);
		}
	}

View on GitHub (pinned to 270dfe353f)