{"record":{"id":"0d14ac36a6c97640","repo":"sebastianbergmann/phpunit","slug":"not-enough-parameter-sets-configured-only-d-para-0d14ac","errorCode":null,"errorMessage":"Not enough parameter sets configured, only %d parameter sets given for %s::%s()","messagePattern":"Not enough parameter sets configured, only (.+?) parameter sets given for (.+?)::(.+?)\\(\\)","errorType":"exception","errorClass":"NoMoreParameterSetsConfiguredException","httpStatus":null,"severity":"error","filePath":"src/Framework/MockObject/Runtime/Rule/PartiallyOrderedParameterSets.php","lineNumber":95,"sourceCode":"        if (count($ordered) > 0 && count($unordered) === 0) {\n            $this->ordered = new OrderedParameterSets($ordered);\n        } else {\n            $this->stack = $ordered;\n        }\n\n        if (count($unordered) > 0) {\n            $this->unordered = new UnorderedParameterSets($unordered);\n        }\n\n        $this->numberOfConfiguredParameterSets = count($stack);\n    }\n\n    public function apply(BaseInvocation $invocation): void\n    {\n        $this->numberOfInvocations++;\n\n        if ($this->numberOfInvocations > $this->numberOfConfiguredParameterSets) {\n            throw new NoMoreParameterSetsConfiguredException(\n                $invocation,\n                $this->numberOfConfiguredParameterSets,\n            );\n        }\n\n        $stack = $this->stack;\n\n        foreach ($stack as $index => $parameters) {\n            if ($parameters->at() === $this->numberOfInvocations - 1) {\n                unset($stack[$index]);\n\n                $this->stack     = array_values($stack);\n                $this->applied[] = $parameters;\n\n                $parameters->apply($invocation);\n\n                return;\n            }","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/sebastianbergmann/phpunit/blob/f123cdb2a2d49f15025794166cfed8bda8627dd2/src/Framework/MockObject/Runtime/Rule/PartiallyOrderedParameterSets.php#L77-L113","documentation":"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.","triggerScenarios":"$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.","commonSituations":"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.","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."],"exampleFix":"// before\n$bus->expects($this->any())->method('dispatch')\n    ->withParameterSetsInPartialOrder(['start'], ['end']);\nforeach ($jobs as $job) { $bus->dispatch('start'); $bus->dispatch('end'); } // 2n calls, only 2 sets\n\n// after: configure a set for each expected call\n$bus->expects($this->exactly(2 * count($jobs)))->method('dispatch')\n    ->withParameterSetsInPartialOrder(...$expectedCalls);","handlingStrategy":"try-catch","validationCode":"// Make the total deterministic before configuring partial-order sets:\n// number of sets must equal number of expected invocations.\n$calls = [['start'], ...array_map(fn ($j) => [$j], $jobs), ['end']];\n$mock->expects($this->exactly(count($calls)))->method('dispatch')\n    ->withParameterSetsInPartialOrder(...$calls);","typeGuard":null,"tryCatchPattern":"use PHPUnit\\Framework\\MockObject\\NoMoreParameterSetsConfiguredException;\ntry {\n    $sut->run($jobs);\n} catch (NoMoreParameterSetsConfiguredException $e) {\n    self::fail('Invocation exceeded configured parameter sets: ' . $e->getMessage());\n}","preventionTips":["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."],"tags":["phpunit","mock","parameter-sets","partial-order","consecutive-calls"],"backgroundTag":"mock-parameter-set-mismatch","analyzedSha":"f123cdb2a2d49f15025794166cfed8bda8627dd2","analyzedAt":"2026-08-23T01:20:58.058Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}