laravel/framework · error · InvalidArgumentException

Scoped disk is missing "disk" configuration option.

Error message

Scoped disk is missing "disk" configuration option.

What it means

Thrown by FilesystemManager::createScopedDriver() when the scoped disk config has no 'disk' key. A scoped driver wraps another disk to apply a path prefix; without knowing which parent disk to scope, it cannot be built.

Solutions

  1. Add 'disk' => 's3' (or another configured disk name / inline array) to the scoped disk config.
  2. Ensure the referenced parent disk itself resolves without error.
  3. Re-run php artisan config:clear after editing.
  4. Document each scoped disk with both 'disk' and 'prefix'.

Example fix

// before
'thumbnails' => [
    'driver' => 'scoped',
    'prefix' => 'thumbnails',
],

// after
'thumbnails' => [
    'driver' => 'scoped',
    'disk' => 's3',
    'prefix' => 'thumbnails',
],
Defensive patterns

Strategy: validation

Validate before calling

if (empty(config("filesystems.disks.{$name}.disk"))) {
    throw new InvalidArgumentException("Scoped disk [{$name}] missing 'disk' option.");
}

Type guard

function scopedDiskHasParent(string $name): bool {
    return ! empty(config("filesystems.disks.{$name}.disk"));
}

Try / catch

try {
    Storage::disk($name);
} catch (\InvalidArgumentException $e) {
    report($e);
}

Prevention

When it happens

Trigger: Defining a disk with 'driver' => 'scoped' in config/filesystems.php but omitting the 'disk' option that names the underlying disk (or passing such config to Storage::build()).

Common situations: Misreading the scoped driver docs; renaming the parent disk key without updating scoped configs; copy-paste config missing the disk line; expecting the scope to default to the default disk.

Related errors


AI-assisted analysis of laravel/framework@e0f6eb3518 (2026-08-11). Data as JSON: /api/errors/e033f7602f97f038. Report an issue: GitHub.

Appendix: source

Thrown at src/Illuminate/Filesystem/FilesystemManager.php:301

                $config['credentials']['token'] = $config['token'];
            }
        }

        return Arr::except($config, ['token']);
    }

    /**
     * Create a scoped driver.
     *
     * @param  array  $config
     * @return \Illuminate\Contracts\Filesystem\Filesystem
     *
     * @throws \InvalidArgumentException
     */
    public function createScopedDriver(array $config)
    {
        if (empty($config['disk'])) {
            throw new InvalidArgumentException('Scoped disk is missing "disk" configuration option.');
        } elseif (empty($config['prefix'])) {
            throw new InvalidArgumentException('Scoped disk is missing "prefix" configuration option.');
        }

        return $this->build(tap(
            is_string($config['disk']) ? $this->getConfig($config['disk']) : $config['disk'],
            function (&$parent) use ($config) {
                if (empty($parent['prefix'])) {
                    $parent['prefix'] = $config['prefix'];
                } else {
                    $separator = $parent['directory_separator'] ?? DIRECTORY_SEPARATOR;

                    $parentPrefix = rtrim($parent['prefix'], $separator);
                    $scopedPrefix = ltrim($config['prefix'], $separator);

                    $parent['prefix'] = "{$parentPrefix}{$separator}{$scopedPrefix}";
                }

View on GitHub (pinned to e0f6eb3518)