pestphp/pest · critical · RuntimeException

Unable to create test case for test file at [%s]. %s

Error message

Unable to create test case for test file at [%s]. 
 %s

What it means

For every test file, TestCaseFactory generates a PHP test-case class (filename constant, trait code, method code) and evals it. If the generated source fails to parse, the ParseError is caught and rethrown as a RuntimeException containing the test file path and the full generated class code — so the exception message doubles as a debugging dump of what Pest built. It is rare and usually signals either an exotic test file or a Pest code-generation bug.

Source

Thrown at src/Factories/TestCaseFactory.php:172

            use Pest\Exceptions\DatasetProviderError as __PestDatasetProviderError;
            use Pest\Repositories\DatasetsRepository as __PestDatasets;
            use Pest\TestSuite as __PestTestSuite;

            $attributesCode
            #[\AllowDynamicProperties]
            final class $className extends $baseClass implements $hasPrintableTestCaseClassFQN {
                $traitsCode

                public static \$__filename = $filenameLiteral;

                $methodsCode
            }
            PHP;

            eval($classCode);
        } catch (ParseError $caught) {
            throw new RuntimeException(sprintf(
                "Unable to create test case for test file at [%s]. \n %s",
                $filename,
                $classCode
            ), 1, $caught);
        }
    }

    public function addMethod(TestCaseMethodFactory $method): void
    {
        if ($method->description === null) {
            throw new TestDescriptionMissing($method->filename);
        }

        if (array_key_exists($method->description, $this->methods)) {
            throw new TestAlreadyExist($method->filename, $method->description);
        }

        if (

View on GitHub (pinned to 1af74a215c)

Solutions

  1. Read the generated class code embedded in the exception message and locate the malformed fragment — usually the method name or trait list derived from your test file.
  2. Simplify/rename the offending pieces: ASCII filenames, plain test descriptions, standard uses() usage; then re-run.
  3. Reinstall a clean dependency tree (rm -rf vendor composer.lock && composer install) to rule out half-upgraded codegen.
  4. If the generated code looks wrong for a normal test file, report it to pestphp/pest including the message — it is likely a codegen bug.

Example fix

// before: test file with an exotic name "2024‑07 ✔.php" -> generated class fails to parse
// after: rename the file to plain ASCII
git mv "tests/2024-07 ✔.php" tests/ReleaseSmokeTest.php
Defensive patterns

Strategy: try-catch

Try / catch

try {
    $factory->buildTestCaseFor($filename);
} catch (RuntimeException $e) {
    // message embeds the generated class code — dump it for the bug report
    file_put_contents(__DIR__.'/pest-generated-dump.php', $e->getMessage());
    throw $e;
}

Prevention

When it happens

Trigger: A test file whose name or test descriptions produce class/method code the generator cannot quote safely; trait composition (uses()) injecting code that breaks the generated class; version mismatches after upgrading Pest or PHP where codegen assumptions changed; eval() disabled is not the cause here (that raises a different error) — a genuine parse failure is.

Common situations: Upgrading Pest across major versions with stale caches or mixed old/new vendor files; unusual filenames (spaces, unicode) for test files; projects generating Pest files programmatically with unescaped content; PHP version changes altering acceptable syntax in eval'd code.

Related errors


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