sebastianbergmann/phpunit · error · Exception

Option %s requires a non-empty value

Error message

Option %s requires a non-empty value

What it means

requireNonEmptyValue() (src/TextUI/Configuration/Cli/Builder.php:1693) guards options whose value must be a non-empty string: --group, --exclude-group, --covers, --uses, --requires-php-extension, --test-suffix, --coverage-filter, --log-events-text, --log-events-verbose-text, and --extension. It throws when getopt hands the Builder null or '' for one of these. The message names the offending option.

Source

Thrown at src/TextUI/Configuration/Cli/Builder.php:1696

     */
    private function parseStopOnValue(?string $value): int
    {
        if (is_numeric($value)) {
            return max(1, (int) $value);
        }

        return 1;
    }

    /**
     * @throws Exception
     *
     * @return non-empty-string
     */
    private function requireNonEmptyValue(?string $value, string $option): string
    {
        if ($value === null || $value === '') {
            throw new Exception(
                sprintf('Option %s requires a non-empty value', $option),
            );
        }

        return $value;
    }

    /**
     * @throws Exception
     *
     * @return positive-int
     */
    private function requirePositiveIntValue(?string $value, string $option): int
    {
        if (!is_numeric($value)) {
            throw new Exception(
                sprintf('Option %s requires a positive integer value', $option),
            );

View on GitHub (pinned to f123cdb2a2)

Solutions

  1. Give the option a non-empty value, e.g. `--group=unit`
  2. Guard the shell expansion so the flag disappears when the variable is empty: `${GROUP:+--group "$GROUP"}`
  3. Provide a default: `--group "${GROUP:-default}"`

Example fix

# before
vendor/bin/phpunit --exclude-group "$EXCLUDED"
# EXCLUDED="" -> Option --exclude-group requires a non-empty value

# after
vendor/bin/phpunit ${EXCLUDED:+--exclude-group "$EXCLUDED"} tests
Defensive patterns

Strategy: validation

Validate before calling

// Wrapper-side guard for every value-taking option you forward
$forwarded = [];

foreach (['--group', '--exclude-group', '--covers', '--uses', '--test-suffix', '--coverage-filter', '--extension'] as $opt) {
    $val = getopt('', ['group::', 'exclude-group::'])[$opt] ?? null; // or your own source
    // simplest: validate before composing the command
}

// Shell-level guard (recommended):
// vendor/bin/phpunit ${GROUP:+--group "$GROUP"} tests

Try / catch

try {
    $cliConfig = (new \PHPUnit\TextUI\CliArguments\Builder)->fromParameters($argv);
} catch (\PHPUnit\TextUI\CliArguments\Exception $e) {
    if (preg_match('/Option (.+) requires a non-empty value/', $e->getMessage(), $m)) {
        // $m[1] names the flag: supply a value or strip the flag and rebuild argv
    }
}

Prevention

When it happens

Trigger: `vendor/bin/phpunit --group=` (empty string after =); `--exclude-group "$GROUPS"` where the shell variable is empty or unset; CI matrix variables interpolating to ''; `--test-suffix ''` from a wrapper that always passes the flag.

Common situations: Unbound or empty environment variables interpolated into CI commands (GitLab/GitHub Actions/GitLab YAML); Makefiles that always emit the flag; wrappers that pass optional filters unconditionally.

Related errors


AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23). Data as JSON: /api/errors/c73d5d4ce83c0234. Report an issue: GitHub.