Laravel 13.30 adds a chunkBy() collection method that starts a new chunk whenever a resolved key or callback value changes, replacing the common chunkWhile() comparison pattern. Storage::path() now runs through the same WhitespacePathNormalizer used by every other Flysystem call, so paths escaping the disk root throw PathTraversalDetected instead of returning a string pointing outside the disk (code relying on '..' segments will now throw). queue:work prints the worker's stop reason as its final output line and as a structured field with --json, covering nine exit scenarios. Other additions include DevCommands::withoutVendorCommands()/withoutDefaultCommands(), native sqlsrv: DSN parsing for SQL Server, Artisan::commandNamed() for resolving a single command lazily, and Cloud queue total size methods. The release also fixes a route:cache bug that left facades pointed at a discarded application, a 500 error from Request::clamp() on non-numeric input, and several other queue, seeding, and validation issues.
Table of contents
# chunkBy() for Collections# Storage::path() Confined to the Disk Root# Worker Stop Reasons in queue:work# Opting Out of Vendor and Default dev Commands# Native SQL Server DSN Connection Strings# Retrieving a Single Artisan Command# Cloud Queue Totals# Other Fixes and ImprovementsQuestions this post answers
Why does Storage::path() in Laravel now throw an exception for paths with '..' segments?
Laravel 13.30 changed Storage::path() to run arguments through the same WhitespacePathNormalizer that every other Flysystem filesystem call uses, so paths resolving outside the disk root now throw PathTraversalDetected instead of returning a string. Previously path() skipped normalization and could return a native path pointing outside the disk, unlike get(), delete(), and readStream(), which already rejected such input. Code relying on the old behavior with '..' segments will now throw. Track breaking changes like this Laravel Storage::path() fix before they surface in production on daily.dev.
What does chunkBy() do differently from chunkWhile() in Laravel collections?
chunkBy(), added in Laravel 13.30, starts a new chunk whenever a resolved key or callback value changes, capturing the most common comparison pattern people already wrote manually with chunkWhile(). It accepts a key string (resolved via data_get(), so dot notation like 'address.city' works) or a callback, and preserves original keys inside each chunk, for example collect([1,1,2,2,1,1])->chunkBy(fn($v)=>$v) returns [[1,1],[2,2],[1,1]]. Developers comparing collection helpers across Laravel versions can follow additions like chunkBy() on daily.dev.
How do I see why a Laravel queue worker stopped running?
Starting in Laravel 13.30, queue:work writes the worker's stop reason as its final console line, for example 'Worker STOPPED Memory limit exceeded', and outputs it as a structured JSON field when using --json. The WorkerStopReason enum gained a description() method covering nine exit scenarios including memory limit exceeded, maximum run time exceeded, and job timed out; nothing prints under --quiet or --silent. Anyone debugging queue worker crashes can keep up with Laravel queue tooling changes on daily.dev.