mongodb/laravel-mongodb · error · RuntimeException

Read-only Adapter for Flysystem is missing. Try running…

Error message

Read-only Adapter for Flysystem is missing. Try running "composer require league/flysystem-read-only"

What it means

When a GridFS flysystem disk is configured as read-only, the package wraps the adapter in league/flysystem-read-only's ReadOnlyFilesystemAdapter. If that package is not installed, the RuntimeException is thrown telling you exactly which composer package to add.

Solutions

  1. Run: composer require league/flysystem-read-only
  2. If the read-only flag is not needed, remove 'read-only' => true from the disk config.
  3. Verify vendor/league/flysystem-read-only exists after deployment; ensure the package is in require (not require-dev) if used in production.

Example fix

// before
composer install  # flysystem-read-only missing
// after
composer require league/flysystem-read-only
Defensive patterns

Strategy: validation

Validate before calling

if (config('filesystems.disks.gridfs.read-only') && ! class_exists(League\Flysystem\ReadOnly\ReadOnlyFilesystemAdapter::class)) {
    throw new RuntimeException('Run composer require league/flysystem-read-only');
}

Type guard

function readOnlyAdapterAvailable(): bool { return class_exists(League\Flysystem\ReadOnly\ReadOnlyFilesystemAdapter::class); }

Try / catch

try {
    Storage::disk('gridfs-readonly')->files();
} catch (RuntimeException $e) {
    if (str_contains($e->getMessage(), 'flysystem-read-only')) {
        abort(500, 'Server missing league/flysystem-read-only; run composer require.');
    }
    throw $e;
}

Prevention

When it happens

Trigger: Setting 'read-only' => true on a gridfs filesystem disk without league/flysystem-read-only being present in vendor (class_exists check fails).

Common situations: Deploying to a production environment where dev dependencies differ, or adding the read-only flag to config without running composer update/require.

Understand the failure class

Background: "X is not installed. Please install it with pip install Y": missing optional dependency errors — ImportError/ValueError raised when a library's optional extra was never installed — this error's family across 22 libraries.

Related errors


AI-assisted analysis of mongodb/laravel-mongodb@0634653039 (2026-09-15). Data as JSON: /api/errors/fc6744314eb1b69d. Report an issue: GitHub.

Appendix: source

Thrown at src/MongoDBServiceProvider.php:153

                    if (! $connection instanceof Connection) {
                        throw new InvalidArgumentException(sprintf('The database connection "%s" does not use the "mongodb" driver.', $config['connection'] ?? $app['config']['database.default']));
                    }

                    $bucket = $connection->getClient()
                        ->getDatabase($config['database'] ?? $connection->getDatabaseName())
                        ->selectGridFSBucket(['bucketName' => $config['bucket'] ?? 'fs', 'disableMD5' => true]);
                }

                if (! $bucket instanceof Bucket) {
                    throw new InvalidArgumentException(sprintf('Unexpected value for GridFS "bucket" configuration. Expecting "%s". Got "%s"', Bucket::class, get_debug_type($bucket)));
                }

                $adapter = new GridFSAdapter($bucket, $config['prefix'] ?? '');

                /** @see FilesystemManager::createFlysystem() */
                if ($config['read-only'] ?? false) {
                    if (! class_exists(ReadOnlyFilesystemAdapter::class)) {
                        throw new RuntimeException('Read-only Adapter for Flysystem is missing. Try running "composer require league/flysystem-read-only"');
                    }

                    $adapter = new ReadOnlyFilesystemAdapter($adapter);
                }

                /** Prevent using backslash on Windows in {@see FilesystemAdapter::__construct()} */
                $config['directory_separator'] = '/';

                return new FilesystemAdapter(new Filesystem($adapter, $config), $adapter, $config);
            });
        });
    }

    private function registerBoostTools(): void
    {
        if (! class_exists(BoostServiceProvider::class)) {
            return;
        }

View on GitHub (pinned to 0634653039)