pestphp/pest · error · InvalidArgumentException

No sequence expectations defined.

Error message

No sequence expectations defined.

What it means

expect($value)->sequence() with zero arguments throws InvalidArgumentException immediately after the iterable check passes. sequence() exists to assert item-by-item order, so Pest rejects an empty expectation list as a no-op rather than silently passing. The fix is to supply at least one closure or expected value.

Source

Thrown at src/Expectation.php:212

        }

        return new EachExpectation($this);
    }

    /**
     * @template TSequenceValue
     *
     * @param  (callable(self<TValue>, self<string|int>): void)|TSequenceValue  ...$callbacks
     * @return self<TValue>
     */
    public function sequence(mixed ...$callbacks): self
    {
        if (! is_iterable($this->value)) {
            throw new BadMethodCallException('Expectation value is not iterable.');
        }

        if ($callbacks === []) {
            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.');

View on GitHub (pinned to 1af74a215c)

Solutions

  1. Pass at least one closure or expected value: ->sequence(fn ($v) => $v->toBe(1)).
  2. If every item should satisfy the same expectation, use each() instead of sequence().
  3. When generating callbacks dynamically, guard the empty case: if ($expected === []) { expect($items)->toBeEmpty(); return; }.

Example fix

// before
expect($logs)->sequence(...$expectedPatterns); // $expectedPatterns is []
// after
if ($expectedPatterns === []) {
    expect($logs)->toBeEmpty();
} else {
    expect($logs)->sequence(...$expectedPatterns);
}
Defensive patterns

Strategy: validation

Validate before calling

if ($expectedPatterns === []) {
    expect($items)->toBeEmpty();
} else {
    expect($items)->sequence(...$expectedPatterns);
}

Prevention

When it happens

Trigger: expect($items)->sequence(); building the callbacks list dynamically from data that ends up empty ($callbacks = []; ->sequence(...$callbacks)); copy-pasting a sequence() call and deleting its body; intending each() (single callback for all items) and calling sequence() instead.

Common situations: Data-driven tests that compute expected sequences and occasionally receive an empty expectation set; refactors where the sequence body was removed but the call remained; misunderstanding the difference between each() and sequence().

Related errors


AI-assisted analysis of pestphp/pest@1af74a215c (2026-08-21). Data as JSON: /api/errors/8f37a8d871301b71. Report an issue: GitHub.