quarkusio/quarkus · error · RuntimeException
More than one @QuarkusMain method found with name '${name}':
Error message
More than one @QuarkusMain method found with name '${name}': ${classInfo.name()} and ${quarkusMainAnnotations.get(name)} What it means
@QuarkusMain allows naming an entry point via its 'name' attribute. While indexing all @QuarkusMain annotations, MainClassBuildStep builds a name -> class map; encountering a second annotated class with the same name throws this RuntimeException to avoid ambiguity in -Dquarkus.main-class resolution.
Source
Thrown at core/deployment/src/main/java/io/quarkus/deployment/steps/MainClassBuildStep.java:420
public MainClassBuildItem mainClassBuildStep(BuildProducer<GeneratedClassBuildItem> generatedClass,
BuildProducer<BytecodeTransformerBuildItem> transformedClass,
CombinedIndexBuildItem combinedIndexBuildItem,
Optional<QuarkusApplicationClassBuildItem> quarkusApplicationClass,
PackageConfig packageConfig) {
String mainClassName = MAIN_CLASS;
Map<String, String> quarkusMainAnnotations = new HashMap<>();
IndexView index = combinedIndexBuildItem.getIndex();
Collection<AnnotationInstance> quarkusMains = index
.getAnnotations(DotName.createSimple(QuarkusMain.class.getName()));
for (AnnotationInstance i : quarkusMains) {
AnnotationValue nameValue = i.value("name");
String name = "";
if (nameValue != null) {
name = nameValue.asString();
}
ClassInfo classInfo = i.target().asClass();
if (quarkusMainAnnotations.containsKey(name)) {
throw new RuntimeException(
"More than one @QuarkusMain method found with name '" + name + "': "
+ classInfo.name() + " and " + quarkusMainAnnotations.get(name));
}
quarkusMainAnnotations.put(name, sanitizeMainClassName(classInfo, index));
}
MethodInfo mainClassMethod = null;
if (packageConfig.mainClass().isPresent()) {
String mainAnnotationClass = quarkusMainAnnotations.get(packageConfig.mainClass().get());
if (mainAnnotationClass != null) {
mainClassName = mainAnnotationClass;
} else {
mainClassName = packageConfig.mainClass().get();
}
} else if (quarkusMainAnnotations.containsKey("")) {
mainClassName = quarkusMainAnnotations.get("");
}
if (mainClassName.equals(MAIN_CLASS)) {View on GitHub (pinned to e1c734241f)
Solutions
- Give each @QuarkusMain annotation a unique name value
- If you intend the default main, keep exactly one @QuarkusMain without a name and name all others
- Rename or delete the duplicated entry class
- Run a project-wide search for @QuarkusMain to audit all names
Example fix
// before
@QuarkusMain(name="run") public class MainA { ... }
@QuarkusMain(name="run") public class MainB { ... }
// after
@QuarkusMain(name="run-a") public class MainA { ... }
@QuarkusMain(name="run-b") public class MainB { ... } Defensive patterns
Strategy: validation
Validate before calling
Set<String> seen = new HashSet<>();
for (Class<?> c : allAnnotatedClasses) {
QuarkusMain qm = c.getAnnotation(QuarkusMain.class);
String name = qm.name().isEmpty() ? "" : qm.name();
if (!seen.add(name)) {
throw new IllegalStateException("Duplicate @QuarkusMain name: '" + name + "'");
}
} Try / catch
try {
quarkusBuild();
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().startsWith("More than one @QuarkusMain method found")) {
// rename one of the listed classes' @QuarkusMain name
}
throw e;
} Prevention
- Audit @QuarkusMain usages with a project-wide search when adding a new CLI entry
- Always give named entry points explicit unique names
- Only one @QuarkusMain may omit the name attribute
- Rename the annotation value whenever copying an existing main class
When it happens
Trigger: During mainClassBuildStep, an AnnotationInstance target class yields a name that is already a key in quarkusMainAnnotations — two classes (or methods) annotated @QuarkusMain(name="same") or both with the empty default name.
Common situations: Two CLI entry classes annotated with the same @QuarkusMain name; two @QuarkusMain classes both left without an explicit name (both map to ""); copy-pasting a main class and forgetting to change the name attribute.
Related errors
- Failed to open path tree with root %s
- Dev services for ${request.getName()} requires a startable s
- Name cannot start with '/':${name}
- The class (${name}) cannot be created during deployment.
- Use GeneratedServiceProviderBuildItem to register service pr
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/b07ba4e139bcb7d1.
Report an issue: GitHub.