getgrav/grav · error · RuntimeException

500

500

Error message

Internal Error

What it means

During Install::prepare(), Grav resolves its own installer directory with `realpath(__DIR__)`; if that returns false it throws RuntimeException 500 'Internal Error'. realpath() fails when the path cannot be resolved at all — the directory was deleted or replaced mid-run, a symlink loop exists, or a path component lost permissions. It is a defensive environment sanity check and is exceptionally rare.

Source

Thrown at system/src/Grav/Installer/Install.php:308

        $this->checkVersion($results, 'grav', 'grav', $this->requires['grav'], GRAV_VERSION);
        $this->checkPlugins($results, $this->requires['plugins']);

        return $results;
    }

    /**
     * @return void
     * @throws RuntimeException
     */
    public function prepare(): void
    {
        // Locate the new Grav update and the target site from the filesystem.
        $this->ensureLocation();
        $location = realpath(__DIR__);
        $target = realpath(GRAV_ROOT . '/index.php');

        if (!$location) {
            throw new RuntimeException('Internal Error', 500);
        }

        if ($target && dirname($location, 4) === dirname($target)) {
            // We cannot copy files into themselves, abort!
            throw new RuntimeException('Grav has already been installed here!', 400);
        }

        // Load the installer classes.
        foreach ($this->classMap as $class_name => $path) {
            // Make sure that none of the Grav\Installer classes have been loaded, otherwise installation may fail!
            if (class_exists($class_name, false)) {
                throw new RuntimeException(sprintf('Cannot update Grav, class %s has already been loaded!', $class_name), 500);
            }

            require $path;
        }

        $this->legacySupport();

View on GitHub (pinned to 6040efed04)

Solutions

  1. Re-run direct-install from a stable, fully-present codebase — the previous attempt was racing a deploy or the tree was incomplete
  2. Check the deployment layout for dangling/looping symlinks around GRAV_ROOT and system/
  3. Verify directory permissions on every path component of the installer directory
Defensive patterns

Strategy: validation

Validate before calling

// Sanity-check the codebase before invoking the installer
$installerDir = realpath(GRAV_ROOT . '/system/src/Grav/Installer');
if ($installerDir === false || !is_dir($installerDir) || !is_readable($installerDir)) {
    throw new \RuntimeException('Installer directory missing or unreadable — codebase incomplete');
}

Prevention

When it happens

Trigger: The system/src/Grav/Installer directory being deleted, moved, or having its symlink chain broken while direct-install runs; a symlink loop in the deployment layout; permissions revoked on a parent directory between process start and the realpath call.

Common situations: Deploys that rsync-delete the codebase concurrently with an upgrade; broken symlink-based release directories (capistrano-style layouts pointing at a removed release).

Related errors


AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17). Data as JSON: /api/errors/f5b5f807db4b60ec. Report an issue: GitHub.