pestphp/pest · error · OutOfRangeException
Sequence expectations are more than the iterable items.
Error message
Sequence expectations are more than the iterable items.
What it means
sequence() applies callbacks in order and wraps back to the first callback when items outnumber callbacks; the opposite direction is an error. After iterating, Pest throws OutOfRangeException if valuesCount < count($callbacks) — you declared more sequence expectations than the iterable has items (including the case where the iterable is empty and any callbacks were given).
Source
Thrown at src/Expectation.php:230
throw new InvalidArgumentException('No sequence expectations defined.');
}
$index = $valuesCount = 0;
foreach ($this->value as $key => $value) {
$valuesCount++;
if ($callbacks[$index] instanceof Closure) {
$callbacks[$index](new self($value), new self($key));
} else {
new self($value)->toEqual($callbacks[$index]);
}
$index = isset($callbacks[$index + 1]) ? $index + 1 : 0;
}
if ($valuesCount < count($callbacks)) {
throw new OutOfRangeException('Sequence expectations are more than the iterable items.');
}
return $this;
}
/**
* @template TMatchSubject of array-key
*
* @param (callable(): TMatchSubject)|TMatchSubject $subject
* @param array<TMatchSubject, (callable(self<TValue>): mixed)|TValue> $expressions
* @return self<TValue>
*/
public function match(mixed $subject, array $expressions): self
{
$subject = $subject instanceof Closure ? $subject() : $subject;
$matched = false;
View on GitHub (pinned to 1af74a215c)
Solutions
- Match the counts: remove surplus sequence entries so count(callbacks) <= count(items).
- If the item count is legitimately variable, rely on wrap-around: keep only as many callbacks as the guaranteed prefix and let the last one repeat.
- Fix the data producer so it returns the full expected set (e.g., correct the query/mocking that dropped rows).
- Assert the size first: expect($items)->toHaveCount(3) before sequence() to fail with a clearer message.
Example fix
// before
expect([1, 2])->sequence(
fn ($v) => $v->toBe(1),
fn ($v) => $v->toBe(2),
fn ($v) => $v->toBe(3), // more expectations than items
);
// after
expect([1, 2])->sequence(
fn ($v) => $v->toBe(1),
fn ($v) => $v->toBe(2),
); Defensive patterns
Strategy: validation
Validate before calling
$callbacks = [/* ... */];
$items = [...];
if (count($items) < count($callbacks)) {
throw new LogicException(
'sequence() needs at least as many items ('.count($items).') as expectations ('.count($callbacks).')'
);
}
expect($items)->sequence(...$callbacks); Prevention
- Pair every sequence() with a preceding expect($items)->toHaveCount(n) so size regressions fail with the clearest message.
- Remember wrap-around: fewer callbacks than items repeats the LAST callback — never the reverse.
- When item counts vary, assert only the stable prefix in sequence() and use each() for the remainder.
When it happens
Trigger: expect([1, 2])->sequence(fn ($v) => $v->toBe(1), fn ($v) => $v->toBe(2), fn ($v) => $v->toBe(3)); expect([])->sequence(fn ($v) => ...); a dataset/pagination result with fewer rows than the expected sequence; off-by-one when counting items.
Common situations: API responses that return fewer records than expected (filtered/empty results); mocks or factories configured to produce fewer entities than the test's sequence asserts; forgetting that sequence wraps — the LAST callback repeats for surplus items, so extra expectations cannot be absorbed.
Related errors
- No sequence expectations defined.
- Expectation value is not iterable.
- Unhandled match value.
- Method [%s] does not exist in [%s].
- Expecting %s not %s %s.
AI-assisted analysis of pestphp/pest@1af74a215c (2026-08-21).
Data as JSON: /api/errors/2d9eadd3097cc545.
Report an issue: GitHub.