sebastianbergmann/phpunit · error · NoMoreParameterSetsConfiguredException
Not enough parameter sets configured, only %d parameter sets
Error message
Not enough parameter sets configured, only %d parameter sets given for %s::%s()
What it means
Thrown at call time when a method configured with withParameterSetsInPartialOrder(...) receives more invocations than the total number of parameter sets you configured. PartiallyOrderedParameterSets::apply() increments a counter on every invocation and raises NoMoreParameterSetsConfiguredException as soon as the count exceeds numberOfConfiguredParameterSets, naming the class::method involved. Partial order means unpinned sets may match in any order while 'pinned' sets are tied to a specific call position — but the total number of calls is still capped by the number of sets.
Source
Thrown at src/Framework/MockObject/Runtime/Rule/PartiallyOrderedParameterSets.php:95
if (count($ordered) > 0 && count($unordered) === 0) {
$this->ordered = new OrderedParameterSets($ordered);
} else {
$this->stack = $ordered;
}
if (count($unordered) > 0) {
$this->unordered = new UnorderedParameterSets($unordered);
}
$this->numberOfConfiguredParameterSets = count($stack);
}
public function apply(BaseInvocation $invocation): void
{
$this->numberOfInvocations++;
if ($this->numberOfInvocations > $this->numberOfConfiguredParameterSets) {
throw new NoMoreParameterSetsConfiguredException(
$invocation,
$this->numberOfConfiguredParameterSets,
);
}
$stack = $this->stack;
foreach ($stack as $index => $parameters) {
if ($parameters->at() === $this->numberOfInvocations - 1) {
unset($stack[$index]);
$this->stack = array_values($stack);
$this->applied[] = $parameters;
$parameters->apply($invocation);
return;
}View on GitHub (pinned to f123cdb2a2)
Solutions
- Use the class::method name in the message plus the stack trace to find the call that ran out of sets.
- Add one parameter set per expected invocation, or wrap the remaining calls with a separate matcher if the tail of the interaction is unpredictable.
- If the total call count is variable, replace the strict set list with withParameterSetsInAnyOrder() for the free calls plus expects($this->exactly(n)), or capture calls in a willReturnCallback() and assert afterwards.
- Shrink or fix the fixture so the number of calls is deterministic and matches the configured sets.
- If the excess invocation is duplicated work in production code, fix the caller rather than expanding the expectation.
Example fix
// before
$bus->expects($this->any())->method('dispatch')
->withParameterSetsInPartialOrder(['start'], ['end']);
foreach ($jobs as $job) { $bus->dispatch('start'); $bus->dispatch('end'); } // 2n calls, only 2 sets
// after: configure a set for each expected call
$bus->expects($this->exactly(2 * count($jobs)))->method('dispatch')
->withParameterSetsInPartialOrder(...$expectedCalls); Defensive patterns
Strategy: try-catch
Validate before calling
// Make the total deterministic before configuring partial-order sets:
// number of sets must equal number of expected invocations.
$calls = [['start'], ...array_map(fn ($j) => [$j], $jobs), ['end']];
$mock->expects($this->exactly(count($calls)))->method('dispatch')
->withParameterSetsInPartialOrder(...$calls); Try / catch
use PHPUnit\Framework\MockObject\NoMoreParameterSetsConfiguredException;
try {
$sut->run($jobs);
} catch (NoMoreParameterSetsConfiguredException $e) {
self::fail('Invocation exceeded configured parameter sets: ' . $e->getMessage());
} Prevention
- Count your sets against the loop bounds in the fixture; both must move together.
- Use 'pinned' sets only for position-critical calls and keep free sets for the variable middle.
- When migrating from withConsecutive(), write one set per old array argument and verify none were dropped.
- For open-ended call counts, capture calls with a callback and assert the sequence afterwards instead of fixed sets.
When it happens
Trigger: $mock->method('record')->withParameterSetsInOrder(...)->withParameterSetsInPartialOrder(['a'], ['b'], ['c']) while the code calls record() a fourth time; the exception propagates out of the fourth $mock->record(...) call inside the code under test, aborting the test at that point.
Common situations: Loops over fixtures with more items than configured sets; a retry path or repeated event firing adding calls; migrating old withConsecutive() tests and losing a set in translation; growing a data provider without extending the parameter sets; mixing pinned ('pinned' => [...]) and free sets and miscounting the total.
Related errors
- Not enough parameter sets configured, only %d parameter sets
- Too many parameter sets given, %d out of %d expected paramet
- Expected invocation at least %d time%s but it occurred %d ti
- Expected invocation at least once but it never occurred.
- Expected invocation at most %d time%s but it occurred %d tim
AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23).
Data as JSON: /api/errors/0d14ac36a6c97640.
Report an issue: GitHub.