laravel/framework · error · InvalidArgumentException
A {$className} class already exists.
Error message
A {$className} class already exists. What it means
Thrown by MigrationCreator::ensureMigrationDoesntAlreadyExist when PHP's class_exists() reports that the migration class name derived from the migration name is already loaded. Laravel derives a ClassName from the snake_case migration name; if two migrations resolve to the same class (or the class exists anywhere in the autoloader) the generator refuses to overwrite. This protects against duplicate migration definitions that would silently collide at runtime.
Source
Thrown at src/Illuminate/Database/Migrations/MigrationCreator.php:109
*
* @param string $name
* @param string|null $migrationPath
* @return void
*
* @throws \InvalidArgumentException
*/
protected function ensureMigrationDoesntAlreadyExist($name, $migrationPath = null)
{
if (! empty($migrationPath)) {
$migrationFiles = $this->files->glob($migrationPath.'/*.php');
foreach ($migrationFiles as $migrationFile) {
$this->files->requireOnce($migrationFile);
}
}
if (class_exists($className = $this->getClassName($name))) {
throw new InvalidArgumentException("A {$className} class already exists.");
}
}
/**
* Get the migration stub file.
*
* @param string|null $table
* @param bool $create
* @return string
*/
protected function getStub($table, $create)
{
if (is_null($table)) {
$stub = $this->files->exists($customPath = $this->customStubPath.'/migration.stub')
? $customPath
: $this->stubPath().'/migration.stub';
} elseif ($create) {
$stub = $this->files->exists($customPath = $this->customStubPath.'/migration.create.stub')View on GitHub (pinned to bd6b5437e6)
Solutions
- Rename the new migration on the command line: `php artisan make:migration create_users_table_v2` so the derived class differs.
- Search the codebase for the colliding class name (`grep -R "class CreateUsersTable"`) and remove or rename the old definition, then run `composer dump-autoload`.
- If the duplicate file was deleted but the autoloader still resolves the class, clear APCu/opcache and run `composer dump-autoload -o`.
- Delete the half-written migration stub from database/migrations before re-running the make command.
Example fix
// before php artisan make:migration create_users_table // => A CreateUsersTable class already exists. // after php artisan make:migration create_users_table_v2 --create=users
Defensive patterns
Strategy: validation
Validate before calling
use Illuminate\Support\Str;
$className = Str::studly(preg_replace('/\d{4}_\d{2}_\d{2}_\d{6}_/', '', $migrationName));
if (class_exists($className)) {
throw new RuntimeException("Migration class {$className} already exists; pick a new name.");
} Type guard
// none: class existence is a runtime autoloader check, not a type narrow.
function migrationClassExists(string $name): bool
{
return class_exists(Str::studly(Str::afterLast($name, '_')));
} Try / catch
// Migration creation is a build-time step; validate/guard the name rather than try/catch. // If you must, catch \InvalidArgumentException in the command runner and prompt for a new name.
Prevention
- Use a consistent naming convention that includes a purpose suffix to avoid class-name collisions.
- Run `composer dump-autoload` after deleting migration files so stale classmap entries are purged.
- Never copy a migration file without renaming both the file and the inner class.
When it happens
Trigger: Calling `php artisan make:migration create_users_table` when a `CreateUsersTable` class already exists in database/migrations (or anywhere autoloaded). Re-running the make command after a failed/half-written run. Naming two migrations such that their StudlyCase derivatives collide (e.g. `add_index_to_users` and `add_index_to_users_table` both could resolve similarly if normalized). Composer dump-autoload leaving a stale classmap pointing at a deleted file.
Common situations: Re-scaffolding migrations during TDD; copying a migration file and forgetting to rename the inner class; autoloader holding a cached classmap entry after the file was deleted; running make:migration in a fresh clone before `composer install` populated vendor yet an old class persists in opcache.
Related errors
- The command "%s" does not exist.
- Unable to determine command name from signature.
- Console component [%s] not found.
- Database was not created. Aborting migration.
- Please implement the prunable method on your model.
AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06).
Data as JSON: /data/errors/2c3643b32821dc6b.json.
Report an issue: GitHub.