rectorphp/rector · error · VersionException

Ensure to run compile from composer git repository clone and

Error message

Ensure to run compile from composer git repository clone and that git binary is available.

What it means

VersionResolver::resolvePackageVersion() runs during Rector's own compile step (building the phar/scoped release) to bake a version string into the binary. It first shells out to `git tag --points-at`; if git exits with a non-zero code it throws VersionException, because the build requires metadata from a git checkout. The packaged constants (VersionResolver::PACKAGE_VERSION) are pre-baked, so normal end-user runs never execute this path.

Source

Thrown at src/Application/VersionResolver.php:37

     * @api
     * @var string
     */
    public const PACKAGE_VERSION = '83496b5d65035792e7b8eea3bb083e8f3b16bec0';
    /**
     * @api
     * @var string
     */
    public const RELEASE_DATE = '2026-08-20 18:50:33';
    /**
     * @var int
     */
    private const SUCCESS_CODE = 0;
    public static function resolvePackageVersion(): string
    {
        // resolve current tag
        exec('git tag --points-at', $tagExecOutput, $tagExecResultCode);
        if ($tagExecResultCode !== self::SUCCESS_CODE) {
            throw new VersionException('Ensure to run compile from composer git repository clone and that git binary is available.');
        }
        if ($tagExecOutput !== []) {
            $tag = $tagExecOutput[0];
            if ($tag !== '') {
                return $tag;
            }
        }
        exec('git log --pretty="%H" -n1 HEAD', $commitHashExecOutput, $commitHashResultCode);
        if ($commitHashResultCode !== 0) {
            throw new VersionException('Ensure to run compile from composer git repository clone and that git binary is available.');
        }
        $version = trim($commitHashExecOutput[0]);
        return trim($version, '"');
    }
    public static function resolverReleaseDateTime(): DateTime
    {
        exec('git log -n1 --pretty=%ci HEAD', $output, $resultCode);
        if ($resultCode !== self::SUCCESS_CODE) {

View on GitHub (pinned to 408fcb0ff1)

Solutions

  1. Compile from a real git clone: git clone https://github.com/rectorphp/rector && build inside it
  2. Ensure git is installed and on PATH: git --version must succeed in the build shell
  3. If git reports dubious ownership, run git config --global --add safe.directory /path/to/rector
  4. Do not call resolvePackageVersion()/resolverReleaseDateTime() in your own tooling; use the pre-baked VersionResolver::PACKAGE_VERSION constant instead

Example fix

// before: building from an exported source archive
curl -L https://github.com/rectorphp/rector/archive/refs/heads/main.tar.gz | tar xz
cd rector-main && composer compile  # throws VersionException

// after: clone the repository so git metadata exists
git clone https://github.com/rectorphp/rector.git
cd rector && composer compile
Defensive patterns

Strategy: validation

Validate before calling

// run before compiling
exec('git rev-parse --git-dir 2>/dev/null', $out, $code);
if ($code !== 0 || $out === []) {
    exit('Compile requires a git clone with git on PATH');
}

Try / catch

catch \Rector\Exception\VersionException around the compile step and fail the build with a message pointing to 'clone the repo and install git' rather than retrying.

Prevention

When it happens

Trigger: Compiling rector.phar (or calling VersionResolver::resolvePackageVersion() manually) outside a git clone: source downloaded as a zip/tarball without a .git directory, git binary not installed or not on PATH, or git refusing to run (e.g. 'detected dubious ownership').

Common situations: Building a phar from a GitHub source archive, a CI image without git, or a checkout owned by a different user triggering git's safe.directory check.

Related errors


AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21). Data as JSON: /api/errors/514900c4ac004eb0. Report an issue: GitHub.