Upgraded an app to Laravel 13 and suddenly every artisan command failed:
ERROR The "folio:list" command cannot be found because it is registered under multiple names.
Cause
laravel/folio (v1.1.19, still the latest) ships a ListCommand that extends Laravel's RouteListCommand and tries to
rename it with a property:
#[AsCommand(name: 'folio:list')]
class ListCommand extends RouteListCommand
{
protected $name = 'folio:list';
Doesn't work anymore. Laravel 13's RouteListCommand defines protected $signature = 'route:list ...', and
Illuminate\Console\Command::__construct() checks $signature before $name. The child inherits the signature, so
the command instantiates as route:list while Symfony's lazy command loader advertises it as folio:list. Symfony
resolves it, finds nothing registered under folio:list, and throws.
Folio has no release with a fix, so override it locally.
Fix
1. A command with a proper signature — app/Console/Commands/FolioListCommand.php:
<?php
namespace App\Console\Commands;
use Laravel\Folio\Console\ListCommand;
use Symfony\Component\Console\Attribute\AsCommand;
#[AsCommand(name: 'folio:list')]
class FolioListCommand extends ListCommand
{
protected $signature = 'folio:list
{--json : Output the route list as JSON}
{--method= : Filter the routes by method}
{--action= : Filter the routes by action}
{--name= : Filter the routes by name}
{--domain= : Filter the routes by domain}
{--middleware= : Filter the routes by middleware}
{--path= : Only show routes matching the given path pattern}
{--except-path= : Do not display the routes matching the given path pattern}
{--r|reverse : Reverse the ordering of the routes}
{--sort=uri : The column (domain, method, uri, name, action, middleware, definition) to sort by}
{--except-vendor : Do not display routes defined by vendor packages}
{--only-vendor : Only display routes defined by vendor packages}';
protected $name = 'folio:list';
}
2. Register it in your own app/Providers/FolioServiceProvider.php (the one folio:install published):
use App\Console\Commands\FolioListCommand;
public function boot(): void
{
Folio::path(resource_path('views/pages'))->middleware([
'*' => [
//
],
]);
if ($this->app->runningInConsole()) {
$this->commands([FolioListCommand::class]);
}
}
That's it. The package's broken command still gets registered, but Laravel's lazy command map is keyed by the
AsCommand attribute name, and app providers boot after package providers — so your entry overwrites the package's
folio:list mapping and the broken class is never resolved.
php artisan, folio:list, and route:list all work again, and everything else Folio does is untouched.
