getgrav/grav · critical · RuntimeException

Uploaded archive file is not a valid Grav update package

Error message

Uploaded archive file is not a valid Grav update package

What it means

DirectInstallCommand::upgradeGrav() validates that the extracted archive is a genuine Grav core update package: it must contain system/install.php which, when included, returns a callable that performs the install. If that file is absent or does not return a callable, the archive is rejected with this RuntimeException (whose message is then stored via Installer::setError).

Source

Thrown at system/src/Grav/Console/Gpm/DirectInstallCommand.php:315

    /**
     * @param string $zip
     * @param string $folder
     * @return void
     */
    private function upgradeGrav(string $zip, string $folder): void
    {
        if (!is_dir($folder)) {
            Installer::setError('Invalid source folder');
        }

        try {
            $script = $folder . '/system/install.php';
            /** Install $installer */
            if ((file_exists($script) && $install = include $script) && is_callable($install)) {
                $install($zip);
            } else {
                throw new RuntimeException('Uploaded archive file is not a valid Grav update package');
            }
        } catch (Exception $e) {
            Installer::setError($e->getMessage());
        }
    }
}

View on GitHub (pinned to 6040efed04)

Solutions

  1. Use the official package: download from getgrav.org/download (e.g. grav-v1.7.x.zip) and run `bin/gpm direct-install grav-v1.7.x.zip`.
  2. Verify the archive layout before installing: `unzip -l package.zip | grep 'system/install.php'` — it must sit at the package root.
  3. Re-download the package if the zip is truncated (compare size/checksum) and retry.
  4. If you must install from source, replicate the packaging so system/install.php returning a closure is included at the root.

Example fix

# before
$ unzip -l grav-source-tag.zip   # no system/install.php -> error
$ bin/gpm direct-install grav-source-tag.zip

# after
$ wget https://getgrav.org/download/core/grav/1.7.46 -O grav-upgrade.zip
$ unzip -l grav-upgrade.zip   # contains system/install.php
$ bin/gpm direct-install grav-upgrade.zip
Defensive patterns

Strategy: validation

Validate before calling

// validate the archive before direct-install
$zip = new \ZipArchive();
if ($zip->open($path) !== true || $zip->locateName('system/install.php') === false) {
    exit('Not a valid Grav update package (missing system/install.php); download from getgrav.org' . PHP_EOL);
}
$zip->close();
// proceed: passthru('php bin/gpm direct-install ' . escapeshellarg($path));

Prevention

When it happens

Trigger: Running `bin/gpm direct-install package.zip` with a GitHub 'Source code (zip)' auto-generated archive (no system/install.php), a plugin or theme zip instead of a core Grav package, a manually repacked/filtered zip that dropped system/install.php, or a truncated/corrupted download that extracted incompletely.

Common situations: Trying to update Grav from a GitHub release tag instead of the official getgrav.org package; feeding a locally built artifact into direct-install; downloading over a flaky connection so the zip is cut short; using direct-install on a zip that only contains the grav/ subfolder rather than the package root layout.

Related errors


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