Laravel 13.30 shipped on 1 September 2026. It is a smaller release than Laravel 13.20, but it contains one change you should treat as a security fix, a neat new collection method and a few queue and developer-experience improvements.
Storage::path() is now confined to the disk root
This is the change to read first. Every other storage operation goes through the Flysystem driver, which normalises the path and throws PathTraversalDetected when it escapes the disk root. Storage::path() skipped that step and handed the path straight to the prefixer, so the two disagreed:
Storage::get('../../../.env'); // rejected
Storage::path('../../../.env'); // resolved outside the diskIf your application builds a path from user input and passes the result of Storage::path() to a download response or a file read, that was a path traversal hole. From 13.30, path() normalises the path the same way Flysystem does, so it returns exactly what the driver would use and traversal attempts no longer escape the configured root.
Even with the fix in place, never trust a file name from the request as-is. Validate it against the records you actually stored.
chunkBy for collections
Collections gain chunkBy, a shorthand for grouping adjacent items that share a value. Before, you had to write it with chunkWhile:
$products->chunkWhile(fn ($value, $key, $chunk) => $value->parent == $chunk->last()->parent);Now it is one call:
$products->chunkBy('parent');It is not the same as groupBy. groupBy gathers every matching item wherever it sits; chunkBy only groups items that are next to each other, so a value that appears again later starts a new chunk:
collect([1, 1, 2, 2, 1, 1])->chunkBy(fn ($v) => $v);
// [[1, 1], [2, 2], [1, 1]]That makes it a good fit for already-sorted data, such as rendering a list with a heading each time the date or category changes.
queue:work tells you why it stopped
queue:work now prints the reason a worker stopped, for example hitting its memory limit, directly in its output. Previously you had to listen for the WorkerStopping event and tie it back to the logs yourself. Combined with the memory usage added to that event in 13.20, diagnosing workers that keep restarting is much easier.
On the queue side there are also new size helpers for Laravel Cloud queues, and createPayloadUsing can now be registered directly on the queue manager.
Trimming DevCommands
If you use DevCommands to control what runs with php artisan dev, you can now opt out of whole groups instead of listing command names one by one:
// AppServiceProvider::boot()
DevCommands::withoutVendorCommands(); // ignore commands from packages
DevCommands::withoutDefaultCommands(); // ignore the framework defaultsThe benefit is predictability: a package update can no longer quietly add a new command to your dev workflow.
Request clamps no longer throw on bad input
request()->clamp() used to throw a 500 error when the parameter was empty or not numeric, so a URL like ?per-page= or ?per-page=foo crashed the page. It now falls back to the default value and still applies the minimum and maximum. If you use clamps for pagination limits, broken or hand-edited URLs now degrade gracefully.
Other changes
- Faster wildcard validation — wildcard rule expansion no longer grows quadratically with large arrays.
- SQL Server DSN support — you can connect to Microsoft SQL Server with a DSN connection string.
- Facades after route:cache — the facade application is restored after cached routes boot.
- Seeder failures — the default database connection is restored when seeding fails.
- Read-through disks — visibility is now set on files written to the fallback disk.
- Exception page — HTML in the exception page tooltip is disabled by default.
- Commands by name — a command can be retrieved by name without resolving every registered command.
Should you upgrade?
Yes, and sooner rather than later because of the Storage::path() fix. This is a minor release in the 13.x line, so composer update should be uneventful. Before deploying, search your code for Storage::path( and check that any path built from request data still behaves as you expect.
If you are catching up on the 13.x line, start with the Laravel 13 feature overview and then Laravel 13.20.





