{"id":"700b5f8e47a4ee76","repo":"laravel/framework","slug":"this-driver-does-not-support-creating-temporary-ur-700b5f","errorCode":null,"errorMessage":"This driver does not support creating temporary URLs.","messagePattern":"This driver does not support creating temporary URLs\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/Illuminate/Filesystem/LocalFilesystemAdapter.php","lineNumber":77,"sourceCode":"     * Get a temporary URL for the file at the given path.\n     *\n     * @param  string  $path\n     * @param  \\DateTimeInterface  $expiration\n     * @param  array  $options\n     * @return string\n     *\n     * @throws \\RuntimeException\n     */\n    public function temporaryUrl($path, $expiration, array $options = [])\n    {\n        if ($this->temporaryUrlCallback) {\n            return $this->temporaryUrlCallback->bindTo($this, static::class)(\n                $path, $expiration, $options\n            );\n        }\n\n        if (! $this->providesTemporaryUrls()) {\n            throw new RuntimeException('This driver does not support creating temporary URLs.');\n        }\n\n        $url = call_user_func($this->urlGeneratorResolver);\n\n        return $url->to($url->temporarySignedRoute(\n            'storage.'.$this->disk,\n            $expiration,\n            ['path' => strtr(rawurlencode($path), ['%2F' => '/'])],\n            absolute: false\n        ));\n    }\n\n    /**\n     * Get a temporary upload URL for the file at the given path.\n     *\n     * @param  string  $path\n     * @param  \\DateTimeInterface  $expiration\n     * @param  array  $options","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/laravel/framework/blob/bd6b5437e6ad87bb49f9b426724f07a9f64e9683/src/Illuminate/Filesystem/LocalFilesystemAdapter.php#L59-L95","documentation":"Thrown by LocalFilesystemAdapter::temporaryUrl() when the adapter cannot produce a temporary URL. The local driver only supports temporary URLs when a custom temporaryUrlCallback is registered OR signed-URL serving is enabled ($shouldServeSignedUrls) with a URL-generator resolver. Without either, generating a temporary URL is impossible, so the adapter aborts hard rather than returning a guess. Distinguish from cloud drivers (S3, R2) which always support temporary URLs.","triggerScenarios":"Calling Storage::disk('local')->temporaryUrl($path, Carbon::now()->addMinutes(5)) on a disk whose driver is 'local' and where no temporaryUrlCallback was set with Storage::disk('local')->buildTemporaryUrlsUsing(...). Also reached indirectly via any package that calls temporaryUrl() (e.g. medialibrary, some download-link helpers) against a local disk.","commonSituations":"Copy-pasting S3 presigned-link code onto the default 'local' disk during local development. Using the same Storage facade calls across environments where production uses s3 but staging uses local. Running tests against a local disk while the code assumes S3 semantics. A package that requires temporary URLs being pointed at a local disk.","solutions":["Switch the disk to an S3-compatible driver (s3, that supports temporary URLs) for the environments that need presigned links.","Guard the call: if (Storage::disk($disk)->providesTemporaryUrls()) { ... } before generating the URL.","Register a custom temporary-URL builder on the local disk via Storage::disk('local')->buildTemporaryUrlsUsing(fn ($path, $expiration, $options) => route('local.signed', ...)).","Enable signed-URL serving for the local disk if your app exposes a controller that serves the file from the signed route.","For downloads, fall back to a normal asset/signed-route URL or stream the file directly instead of requesting a temporary URL."],"exampleFix":"// before\n$url = Storage::disk('local')->temporaryUrl('files/report.pdf', now()->addMinutes(5));\n\n// after\nuse Illuminate\\Support\\Facades\\Storage;\n\n$disk = Storage::disk('local');\n\nif ($disk->providesTemporaryUrls()) {\n    $url = $disk->temporaryUrl('files/report.pdf', now()->addMinutes(5));\n} else {\n    // Fallback: signed route served by your own controller\n    $url = URL::temporarySignedRoute('files.download', now()->addMinutes(5), ['path' => 'files/report.pdf']);\n}","handlingStrategy":"validation","validationCode":"use Illuminate\\Support\\Facades\\Storage;\n\n$disk = Storage::disk('local');\nif (! $disk->providesTemporaryUrls()) {\n    // do not call temporaryUrl(); fall back to a signed route or asset URL\n    abort(501, 'Temporary URLs are not supported on this disk.');\n}","typeGuard":"function supportsTemporaryUrls(string $diskName): bool {\n    return Storage::disk($diskName)->providesTemporaryUrls();\n}","tryCatchPattern":"use Illuminate\\Filesystem\\FilesystemAdapter;\n\ntry {\n    $url = Storage::disk($disk)->temporaryUrl($path, $expiration);\n} catch (\\RuntimeException $e) {\n    if (str_contains($e->getMessage(), 'does not support creating temporary URLs')) {\n        // fall back to a signed route / direct stream\n    }\n    throw $e;\n}","preventionTips":["Always call providesTemporaryUrls() before temporaryUrl() when the disk is configurable.","Pin disk choice by environment: use s3/r2 disks for presigned links, local for streaming.","Centralize URL generation behind a service that knows each disk's capability."],"tags":["filesystem","storage","local","temporary-url","runtime-exception"],"analyzedSha":"bd6b5437e6ad87bb49f9b426724f07a9f64e9683","analyzedAt":"2026-08-06T00:28:32.783Z","schemaVersion":2}