laravel/framework · error · RuntimeException

This driver does not support creating temporary upload URLs.

Error message

This driver does not support creating temporary upload URLs.

What it means

Thrown by FilesystemAdapter::temporaryUploadUrl() when the adapter exposes no temporaryUploadUrl() method and no temporaryUploadUrlCallback was registered. Temporary upload URLs let clients push directly to cloud storage (e.g. S3 presigned PUT); they are not supported by local or generic adapters.

Source

Thrown at src/Illuminate/Filesystem/FilesystemAdapter.php:908

     * @param  \DateTimeInterface  $expiration
     * @param  array  $options
     * @return array
     *
     * @throws \RuntimeException
     */
    public function temporaryUploadUrl($path, $expiration, array $options = [])
    {
        if (method_exists($this->adapter, 'temporaryUploadUrl')) {
            return $this->adapter->temporaryUploadUrl($path, $expiration, $options);
        }

        if ($this->temporaryUploadUrlCallback) {
            return $this->temporaryUploadUrlCallback->bindTo($this, static::class)(
                $path, $expiration, $options
            );
        }

        throw new RuntimeException('This driver does not support creating temporary upload URLs.');
    }

    /**
     * Concatenate a path to a URL.
     *
     * @param  string  $url
     * @param  string  $path
     * @return string
     */
    protected function concatPathToUrl($url, $path)
    {
        return rtrim($url, '/').'/'.ltrim($path, '/');
    }

    /**
     * Replace the scheme, host and port of the given UriInterface with values from the given URL.
     *
     * @param  \Psr\Http\Message\UriInterface  $uri

View on GitHub (pinned to bd6b5437e6)

Solutions

  1. Use an S3 disk for temporary upload URLs.
  2. Register a builder: Storage::disk('custom')->buildTemporaryUploadUrlsUsing(fn($path,$exp,$opts) => [...]).
  3. Guard with $disk->providesTemporaryUploadUrls() before calling.
  4. In dev, route uploads through your own controller instead of presigned URLs.

Example fix

// before - local disk has no presigned upload support
[$url, $headers] = Storage::disk('local')->temporaryUploadUrl('uploads/x.txt', now()->addMinutes(5));

// after
if (Storage::disk('s3')->providesTemporaryUploadUrls()) {
    [$url, $headers] = Storage::disk('s3')->temporaryUploadUrl('uploads/x.txt', now()->addMinutes(5));
}
Defensive patterns

Strategy: validation

Validate before calling

$disk = Storage::disk($name);
if (! $disk->providesTemporaryUploadUrls()) {
    abort(400, 'Direct uploads not supported for this disk');
}
return $disk->temporaryUploadUrl($path, $expiration);

Type guard

function diskSupportsTemporaryUploadUrls(\Illuminate\Filesystem\FilesystemAdapter $disk): bool
{
    return $disk->providesTemporaryUploadUrls();
}

Try / catch

try {
    [$url, $headers] = Storage::disk($name)->temporaryUploadUrl($path, $expiration);
} catch (\RuntimeException $e) {
    if (str_contains($e->getMessage(), 'temporary upload URLs')) {
        abort(400, 'Direct upload not available; use the standard upload endpoint.');
    }
    throw $e;
}

Prevention

When it happens

Trigger: Calling Storage::disk($name)->temporaryUploadUrl($path, $expiration) on a disk whose adapter lacks temporaryUploadUrl (local, ftp, sftp, custom) and where buildTemporaryUploadUrlsUsing() was not called.

Common situations: Implementing direct-to-S3 uploads but pointing at the local disk in dev; using a custom cloud adapter that didn't implement the method; forgetting to register the callback.

Related errors


AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06). Data as JSON: /data/errors/373ee28966500558.json. Report an issue: GitHub.