flarum/framework · critical · UnreadableManifestException

Cannot read the installed package manifest at $path…

Error message

Cannot read the installed package manifest at $path: $reason. Flarum cannot determine which extensions are installed until this is resolved, which usually means completing or re-running `composer install`. (the file does not exist)

What it means

ExtensionManager::getExtensions reads composer's installed.json manifest; if the file does not exist, it throws UnreadableManifestException via missing(), reporting that Flarum cannot determine installed extensions until `composer install` completes. It blocks extension loading at boot.

Solutions

  1. Run `composer install` in the Flarum root to (re)generate installed.json
  2. Verify the configured vendor path points to the real composer vendor directory
  3. Re-run a previously failed composer install and check for composer errors
  4. Restore the vendor directory from a good deploy artifact

Example fix

// before
# vendor/composer/installed.json missing
// after
composer install
Defensive patterns

Strategy: try-catch

Validate before calling

$manifest = $paths->vendor.'/composer/installed.json';
if (!file_exists($manifest)) { /* fail fast: run composer install */ }

Type guard

function manifestExists($vendorPath): bool {
  return is_file($vendorPath.'/composer/installed.json');
}

Try / catch

try {
    $extensions = $manager->getExtensions();
} catch (UnreadableManifestException $e) {
    logger()->critical('Composer manifest unreadable: run composer install');
    abort(500, 'Extensions unavailable');
}

Prevention

When it happens

Trigger: Accessing getExtensions()/getEnabledExtensions()/getExtension() when {vendor}/composer/installed.json is absent — vendor directory missing, truncated, or never generated.

Common situations: Fresh clones where composer install was not run, failed/partial composer installs, deploys that exclude vendor or run composer with wrong paths.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of flarum/framework@4b939f6853 (2026-09-15). Data as JSON: /api/errors/800b4ab8c785a4d1. Report an issue: GitHub.

Appendix: source

Thrown at framework/core/src/Extension/ExtensionManager.php:59

        protected Paths $paths,
        protected Container $container,
        protected Migrator $migrator,
        protected Dispatcher $dispatcher,
        protected Filesystem $filesystem,
        protected MaintenanceMode $maintenance,
    ) {
    }

    /**
     * @return Collection<string, Extension>
     */
    public function getExtensions(): Collection
    {
        if (is_null($this->extensions)) {
            $manifest = $this->paths->vendor.'/composer/installed.json';

            if (! $this->filesystem->exists($manifest)) {
                throw UnreadableManifestException::missing($manifest);
            }

            /** @var Collection<string, Extension> $extensions */
            $extensions = new Collection();

            // Load all packages installed by composer.
            $installed = json_decode($this->filesystem->get($manifest), true);

            if (! is_array($installed)) {
                throw UnreadableManifestException::unparsable($manifest);
            }

            // Composer 2.0 changes the structure of the installed.json manifest
            $installed = $installed['packages'] ?? $installed;

            if (! is_array($installed)) {
                throw UnreadableManifestException::unparsable($manifest);
            }

View on GitHub (pinned to 4b939f6853)