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

  1. Set the property to 'discovery' or 'execution' (case-insensitive), e.g. -Djunit.platform.discovery.issue.failure.phase=execution.
  2. Remove the property entirely to let the Launcher pick the phase automatically based on whether discover() or execute() is called.
  3. Inspect junit-platform.properties on the classpath and any -D JVM args for typos, surrounding quotes, or trailing whitespace.
  4. 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

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


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)