junit-team/junit5 · error · JUnitException
Invalid LauncherPhase
Error message
Invalid LauncherPhase '%s' set via the '%s' configuration parameter.
What it means
Thrown as a JUnitException by LauncherPhase.getDiscoveryIssueFailurePhase() when the configuration property 'junit.platform.discovery.issue.failure.phase' cannot be mapped to one of the two enum constants DISCOVERY or EXECUTION. The value is parsed via LauncherPhase.valueOf(value.toUpperCase(Locale.ROOT)), so only 'discovery' and 'execution' (case-insensitive) are accepted. It signals a user-supplied configuration error, not a runtime/environment problem.
Solutions
- Set the property to 'discovery' or 'execution' (case-insensitive), e.g. -Djunit.platform.discovery.issue.failure.phase=execution.
- Remove the property entirely to let the Launcher pick the phase automatically based on whether discover() or execute() is called.
- Inspect junit-platform.properties on the classpath and any -D JVM args for typos, surrounding quotes, or trailing whitespace.
- If migrating from an older version, confirm the property name and accepted values against the LauncherConstants.DISCOVERY_ISSUE_FAILURE_PHASE_PROPERTY_NAME javadoc for your JUnit version.
Example fix
// before -Djunit.platform.discovery.issue.failure.phase=none // after -Djunit.platform.discovery.issue.failure.phase=execution
Defensive patterns
Strategy: validation
Validate before calling
// Run before launching, against the same ConfigurationParameters / system props.
String key = "junit.platform.discovery.issue.failure.phase";
String value = System.getProperty(key); // or read from junit-platform.properties
if (value != null && !value.isBlank()
&& !"discovery".equalsIgnoreCase(value.trim())
&& !"execution".equalsIgnoreCase(value.trim())) {
throw new IllegalStateException(
"Invalid " + key + "=" + value + ". Use 'discovery' or 'execution'.");
} Try / catch
// JUnitException is unchecked; surface a clear config error to the user.
try {
launcher.execute(request);
} catch (JUnitException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Invalid LauncherPhase")) {
throw new IllegalStateException(
"Fix junit.platform.discovery.issue.failure.phase "
+ "(must be 'discovery' or 'execution').", e);
}
throw e;
} Prevention
- Treat the property as an enum: only the literals 'discovery' and 'execution' are valid.
- Add a preflight config validator in your build plugin that checks junit-platform.properties keys.
- Do not confuse this property with junit.platform.discovery.issue.severity.critical, which takes a Severity name.
- Pin all JUnit artifacts via junit-bom so the property name and accepted values match your version's docs.
When it happens
Trigger: Setting the JVM system property or JUnit Platform config file entry 'junit.platform.discovery.issue.failure.phase' to any string other than 'discovery' or 'execution' — e.g. 'none', 'runtime', 'test', 'discovry' (typo), an empty string, or a value copied from the related severity property. The IllegalArgumentException from LauncherPhase.valueOf() is caught and rethrown with this message during Launcher.discover()/execute() initialization.
Common situations: Confusing this property with the sibling 'junit.platform.discovery.issue.severity.critical' which accepts Severity names (error, warning, etc.); typo while hand-editing junit-platform.properties; trailing whitespace or quotes around the value in a properties file; copy-pasting a value from outdated docs; version mismatch where the property was introduced in 1.13 but the user reads pre-1.13 guidance.
Related errors
- Configuration error: .
- configuration errors:%n
- OutputDirectoryCreator not available; probably due to…
- Cannot override the standard style 'NONE'
- Class must not be null
AI-assisted analysis of junit-team/junit5@f070c699a0 (2026-08-11).
Data as JSON: /api/errors/8641ccfc5ae06263.
Report an issue: GitHub.
Appendix: source
Thrown at junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherPhase.java:38
import org.junit.platform.commons.JUnitException;
import org.junit.platform.engine.ConfigurationParameters;
/**
* The phase the {@link org.junit.platform.launcher.Launcher} is in.
*
* @since 1.13
*/
enum LauncherPhase {
DISCOVERY, EXECUTION;
static Optional<LauncherPhase> getDiscoveryIssueFailurePhase(ConfigurationParameters configurationParameters) {
Function<String, @Nullable LauncherPhase> stringLauncherPhaseFunction = value -> {
try {
return LauncherPhase.valueOf(value.toUpperCase(Locale.ROOT));
}
catch (Exception e) {
throw new JUnitException(
"Invalid LauncherPhase '%s' set via the '%s' configuration parameter.".formatted(value,
DISCOVERY_ISSUE_FAILURE_PHASE_PROPERTY_NAME));
}
};
return configurationParameters.get(DISCOVERY_ISSUE_FAILURE_PHASE_PROPERTY_NAME, stringLauncherPhaseFunction);
}
@Override
public String toString() {
return name().toLowerCase(Locale.ENGLISH);
}
}
View on GitHub (pinned to f070c699a0)