{"id":"d01ffced9b4722b4","repo":"laravel/framework","slug":"the-disk-disk-conflicts-with-the-served-u","errorCode":null,"errorMessage":"The [{$disk}] disk conflicts with the [{$served[$uri]}] disk at [{$uri}]. Each served disk must have a unique URL.","messagePattern":"The \\[(.+?)\\] disk conflicts with the \\[(.+?)\\] disk at \\[(.+?)\\]\\. Each served disk must have a unique URL\\.","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Illuminate/Filesystem/FilesystemServiceProvider.php","lineNumber":102,"sourceCode":"    {\n        if ($this->app instanceof CachesRoutes && $this->app->routesAreCached()) {\n            return;\n        }\n\n        $served = [];\n\n        foreach ($this->app['config']['filesystems.disks'] ?? [] as $disk => $config) {\n            if (! $this->shouldServeFiles($config)) {\n                continue;\n            }\n\n            $this->app->booted(function ($app) use ($disk, $config, &$served) {\n                $uri = isset($config['url'])\n                    ? rtrim(parse_url($config['url'])['path'], '/')\n                    : '/storage';\n\n                if (isset($served[$uri])) {\n                    throw new InvalidArgumentException(\n                        \"The [{$disk}] disk conflicts with the [{$served[$uri]}] disk at [{$uri}]. Each served disk must have a unique URL.\"\n                    );\n                }\n\n                $served[$uri] = $disk;\n\n                $isProduction = $app->isProduction();\n\n                Route::get($uri.'/{path}', function (Request $request, string $path) use ($disk, $config, $isProduction) {\n                    return (new ServeFile(\n                        $disk,\n                        $config,\n                        $isProduction\n                    ))($request, $path);\n                })->where('path', '.*')->name('storage.'.$disk);\n\n                Route::put($uri.'/{path}', function (Request $request, string $path) use ($disk, $config, $isProduction) {\n                    return (new ReceiveFile(","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/laravel/framework/blob/bd6b5437e6ad87bb49f9b426724f07a9f64e9683/src/Illuminate/Filesystem/FilesystemServiceProvider.php#L84-L120","documentation":"Thrown by FilesystemServiceProvider::serveFiles() during boot when two local disks both enable 'serve' => true and would be served from the same URI (default '/storage', or a shared 'url' path). Laravel registers a route per served disk, so each disk must occupy a unique URL prefix; a collision would silently shadow one disk's files behind another's route.","triggerScenarios":"Having two entries in filesystems.disks with 'driver' => 'local' and 'serve' => true that both resolve to the same URI (both default to /storage, or both share the same configured 'url' path).","commonSituations":"Enabling file serving on multiple local disks (e.g. a public and a private-with-prefix disk) without giving each a distinct 'url'; copying a disk config block and forgetting to change the url path.","solutions":["Give each served local disk a unique 'url' key, e.g. '/storage' and '/exports'.","Disable 'serve' on disks that don't need direct serving.","Ensure the 'url' config resolves to distinct path components (parse_url path).","Re-run `php artisan route:cache` (or clear it) after fixing config."],"exampleFix":"// before - two served disks collide at /storage\n// 'public'  => ['driver' => 'local', 'root' => storage_path('app/public'),  'serve' => true],\n// 'private' => ['driver' => 'local', 'root' => storage_path('app/private'), 'serve' => true],\n\n// after - distinct urls\n// 'public'  => ['driver' => 'local', 'root' => storage_path('app/public'),  'serve' => true, 'url' => '/storage'],\n// 'private' => ['driver' => 'local', 'root' => storage_path('app/private'), 'serve' => true, 'url' => '/files'],","handlingStrategy":"validation","validationCode":"// Validate that all served local disks have unique URIs at boot\n$served = [];\nforeach (config('filesystems.disks', []) as $name => $cfg) {\n    if (($cfg['driver'] ?? '') !== 'local' || empty($cfg['serve'])) continue;\n    $uri = isset($cfg['url']) ? rtrim((string) parse_url($cfg['url'], PHP_URL_PATH), '/') : '/storage';\n    if (isset($served[$uri])) {\n        throw new RuntimeException(\"Disk {$name} collides with {$served[$uri]} at {$uri}\");\n    }\n    $served[$uri] = $name;\n}","typeGuard":"function servedUrisAreUnique(): bool\n{\n    $uris = [];\n    foreach (config('filesystems.disks', []) as $cfg) {\n        if (($cfg['driver'] ?? '') !== 'local' || empty($cfg['serve'])) continue;\n        $uri = isset($cfg['url']) ? rtrim((string) parse_url($cfg['url'], PHP_URL_PATH), '/') : '/storage';\n        if (in_array($uri, $uris, true)) return false;\n        $uris[] = $uri;\n    }\n    return true;\n}","tryCatchPattern":"// This fires during boot(); wrap config validation in a boot-time check\n// and surface a clear 500 before routes register.\nif (! servedUrisAreUnique()) {\n    throw new \\InvalidArgumentException('Two served local disks share a URL prefix');\n}","preventionTips":["Give each served local disk a unique 'url'.","Only enable 'serve' => true on disks that need direct serving.","Add a boot-time config validator in a service provider."],"tags":["filesystem","configuration","routing","serving","local-disk"],"analyzedSha":"bd6b5437e6ad87bb49f9b426724f07a9f64e9683","analyzedAt":"2026-08-06T00:28:32.783Z","schemaVersion":2}