sebastianbergmann/phpunit · error · ParameterDoesNotExistException
Parameter "%s" does not exist
Error message
Parameter "%s" does not exist
What it means
Runner extensions receive a ParameterCollection built from the <parameter name="..." value="..."/> child elements of the extension's <bootstrap> block in phpunit.xml. get(string $name) throws ParameterDoesNotExistException(sprintf('Parameter "%s" does not exist', $name)) when no parameter with exactly that name was configured. The sibling method has(string $name) is the safe boolean check.
Source
Thrown at src/Runner/Extension/ParameterCollection.php:54
* @param array<string, string> $parameters
*/
private function __construct(array $parameters)
{
$this->parameters = $parameters;
}
public function has(string $name): bool
{
return array_key_exists($name, $this->parameters);
}
/**
* @throws ParameterDoesNotExistException
*/
public function get(string $name): string
{
if (!array_key_exists($name, $this->parameters)) {
throw new ParameterDoesNotExistException($name);
}
return $this->parameters[$name];
}
}
View on GitHub (pinned to f123cdb2a2)
Solutions
- Add the missing parameter in phpunit.xml inside the extension element: <bootstrap class="Vendor\MyExtension"><parameter name="foo" value="bar"/></bootstrap>.
- Verify the exact name and casing used by the extension; the lookup is case-sensitive.
- In extension code, guard with has() and provide your own default: $value = $parameters->has('foo') ? $parameters->get('foo') : 'default';
Example fix
<!-- before (phpunit.xml) -->
<extensions>
<bootstrap class="Vendor\MyExtension"/>
</extensions>
<!-- after -->
<extensions>
<bootstrap class="Vendor\MyExtension">
<parameter name="apiKey" value="secret"/>
</bootstrap>
</extensions> Defensive patterns
Strategy: type-guard
Validate before calling
// in extension bootstrap(), before any get() call
if (!$parameters->has('apiKey')) {
throw new \RuntimeException(
'MyExtension requires "apiKey": add <parameter name="apiKey" value="..."/> to the <bootstrap> element in phpunit.xml'
);
}
$apiKey = $parameters->get('apiKey'); Type guard
final class SafeParameters
{
public function __construct(
private readonly \PHPUnit\Runner\Extension\ParameterCollection $parameters,
) {
}
public function optional(string $name, string $default): string
{
return $this->parameters->has($name)
? $this->parameters->get($name)
: $default;
}
} Prevention
- Always guard optional parameters with has(); for required ones, check has() first and throw a message that shows the exact XML snippet to add.
- Keep parameter names in a single class constant shared between documentation and code to prevent spelling drift.
- Lint the effective phpunit.xml in CI so missing <parameter> elements fail at configuration-validation time.
When it happens
Trigger: Calling $parameters->get('foo') in an extension's bootstrap() when phpunit.xml has no <parameter name="foo" .../> element for that extension, or when the code and XML names differ in spelling or case (the array_key_exists lookup is exact and case-sensitive).
Common situations: Typo between the XML attribute and the extension code; CI using a different phpunit.xml that lacks the parameter; upgrading an extension that renamed its parameters; forgetting that parameters must be strings and always present (no defaults exist at this layer).
Related errors
- Cannot load XML configuration file %s
- Invalid version comparison operator: "%s"
- The file does not validate against any known schema
- The file does not need to be migrated
- Default test suite is not configured
AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23).
Data as JSON: /api/errors/b012b26db9c08a3a.
Report an issue: GitHub.