junit-team/junit5 · error · ParameterException

Missing required subcommand

Error message

Missing required subcommand

What it means

MainCommand.run() is invoked by picocli when the top-level 'junit' command is called without --help or --version and without any subcommand. Because discover and execute are subcommands, the launcher requires one of them; otherwise it throws a ParameterException that picocli renders as usage plus a non-zero exit code.

Solutions

  1. Append the intended subcommand: 'execute' to run tests or 'discover' to list discovered tests.
  2. If you only want help/version, pass --help / -h or --version to the top-level command.
  3. Check your wrapper script/CI for an empty or malformed args array that drops the subcommand token.

Example fix

// before
java -jar junit-platform-console-standalone.jar
// after
java -jar junit-platform-console-standalone.jar execute --select-class com.example.MyTests
Defensive patterns

Strategy: validation

Validate before calling

// In wrapper scripts, ensure a subcommand is present.
String sub = args.length > 0 ? args[0] : "";
if (!sub.equals("discover") && !sub.equals("execute") && !sub.equals("--help") && !sub.equals("-h") && !sub.equals("--version")) {
  System.err.println("Usage: junit (discover|execute) [options]");
  System.exit(2);
}

Prevention

When it happens

Trigger: Running the console launcher jar with no arguments or with only global options but no subcommand: 'java -jar junit-platform-console-standalone.jar' or '... --disable-banner'. picocli routes to MainCommand.run() and, finding neither help nor version nor a subcommand, raises the error.

Common situations: New users running the jar directly; CI scripts that build the args list dynamically and accidentally pass an empty/whitespace arg; wrapper tools that invoke the launcher without specifying 'discover' or 'execute'.

Related errors


AI-assisted analysis of junit-team/junit5@f070c699a0 (2026-08-11). Data as JSON: /api/errors/49ac0219a4ce3639. Report an issue: GitHub.

Appendix: source

Thrown at junit-platform-console/src/main/java/org/junit/platform/console/command/MainCommand.java:80

	@Nullable
	CommandResult<?> commandResult;

	MainCommand(ConsoleTestExecutor.Factory consoleTestExecutorFactory) {
		this.consoleTestExecutorFactory = consoleTestExecutorFactory;
	}

	@Override
	public void run() {
		if (helpRequested) {
			commandSpec.commandLine().usage(commandSpec.commandLine().getOut());
			commandResult = CommandResult.success();
		}
		else if (versionRequested) {
			commandSpec.commandLine().printVersionHelp(commandSpec.commandLine().getOut());
			commandResult = CommandResult.success();
		}
		else {
			throw new ParameterException(commandSpec.commandLine(), "Missing required subcommand");
		}
	}

	@Override
	public int getExitCode() {
		return requireNonNull(commandResult).getExitCode();
	}

	CommandResult<?> run(String[] args,
			@SuppressWarnings("OptionalUsedAsFieldOrParameterType") Optional<OutputStreamConfig> outputStreamConfig) {
		CommandLine commandLine = new CommandLine(this) //
				.addSubcommand(new DiscoverTestsCommand(consoleTestExecutorFactory)) //
				.addSubcommand(new ExecuteTestsCommand(consoleTestExecutorFactory)) //
				.addSubcommand(new ListTestEnginesCommand());
		return runCommand(commandLine, args, outputStreamConfig);
	}

	private static CommandResult<?> runCommand(CommandLine commandLine, String[] args,

View on GitHub (pinned to f070c699a0)