spring-projects/spring-boot · error · InvalidUserDataException
Main class name has not been configured and it could not be
Error message
Main class name has not been configured and it could not be resolved from classpath {} What it means
Thrown by ResolveMainClassName.ClassNameReader.transform() when the output file produced by resolveMainClassName() is empty, meaning no main class was found on any classpath directory and the user did not configure one. It is raised as an InvalidUserDataException only when the main-class name provider is actually read (lazy), typically when bootJar/bootRun/bootWar or bootBuildImage resolves it.
Source
Thrown at build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/ResolveMainClassName.java:175
.getFiles()
.stream()
.map(File::getAbsolutePath)
.collect(Collectors.joining(File.pathSeparator));
return this.outputFile.map(new ClassNameReader(classpath));
}
private static final class ClassNameReader implements Transformer<String, RegularFile> {
private final String classpath;
private ClassNameReader(String classpath) {
this.classpath = classpath;
}
@Override
public String transform(RegularFile file) {
if (file.getAsFile().length() == 0) {
throw new InvalidUserDataException(
"Main class name has not been configured and it could not be resolved from classpath "
+ this.classpath);
}
Path output = file.getAsFile().toPath();
try {
return Files.readString(output);
}
catch (IOException ex) {
throw new RuntimeException("Failed to read main class name from '" + output + "'");
}
}
}
}
View on GitHub (pinned to 5b2dbdbb8b)
Solutions
- Explicitly set the main class: tasks.named('bootJar') { mainClass.set('com.example.MyApp') } or springBoot { mainClass.set('com.example.MyApp') }.
- Ensure your @SpringBootApplication-annotated class is compiled into the main source set's output directory before bootJar/resolveMainClassName runs.
- If this is a library module, remove the Spring Boot application plugin so main-class resolution is not attempted.
- Run with --info to see which classpath directories were scanned and confirm they contain your classes.
Example fix
// before: no main class configured, resolution fails
tasks.named('bootJar') {
// relies on classpath scan that finds nothing
}
// after: declare the main class explicitly
tasks.named('bootJar') {
mainClass.set('com.example.MyApplication')
}
Defensive patterns
Strategy: validation
Validate before calling
// Configure mainClass explicitly, or assert a main class exists before bootJar
import java.io.File
fun hasApplicationClass(sourceDir: File, fqcn: String): Boolean {
val rel = fqcn.replace('.', '/') + ".class"
return File(sourceDir, rel).exists()
}
// usage in build.gradle.kts
val mainSource = sourceSets.main.get().output.classesDirs.singleFile
tasks.named("bootJar") {
if (!hasApplicationClass(mainSource, "com.example.MyApplication")) {
throw GradleException("Main class missing; set tasks.bootJar.mainClass")
}
mainClass.set("com.example.MyApplication")
}
Prevention
- Always set mainClass explicitly for application modules (springBoot { mainClass.set(...) }).
- Do not apply the Spring Boot application plugin to library modules that have no main class.
- Ensure compileJava produces classes before bootJar by respecting task dependencies.
When it happens
Trigger: resolveAndStoreMainClassName() writes an empty string to outputFile because resolveMainClassName() found no @SpringBootApplication/main class; later readMainClassName()'s ClassNameReader sees file.getAsFile().length()==0 and throws at line 175, embedding the joined classpath directories in the message.
Common situations: Library-only modules with no main class; the main class lives in a source set not wired into the boot classpath; classes are in a jar but the task only scans directories (filter(File::isDirectory)); main source set output dir is empty because compileJava did not run; multi-module setup where the application module was not the one applying the plugin.
Related errors
- Failed to read '{}'
- Failed to set file mode on CopySpec
- Failed to read main class name from '{}'
- Each image building cache can be configured only once
- Invalid Docker configuration, either context or host can be
AI-assisted analysis of spring-projects/spring-boot@5b2dbdbb8b (2026-08-04).
Data as JSON: /data/errors/e48523a9b6454f07.json.
Report an issue: GitHub.