Skip to content

Activating from a git checkout fatals: the committed autoloader requires a dev-only file #436

Description

@redbullpeter

We were working on something else against a checkout of master and ran into this, so passing it along in case it is useful. Not sure whether it is intentional, since the released plugin is unaffected.

Summary: a clean git clone of master cannot be activated. The committed autoloader eagerly requires vendor/phpstan/phpstan/bootstrap.php, which is a dev dependency and is correctly not committed, so the plugin fatals before any of its own code runs.

Steps to reproduce

git clone https://github.com/WPManageNinja/fluent-smtp.git wp-content/plugins/fluent-smtp
wp plugin activate fluent-smtp

No composer install in between. Result:

PHP Fatal error:  Uncaught Error: Failed opening required
'.../wp-content/plugins/fluent-smtp/vendor/composer/../phpstan/phpstan/bootstrap.php'
(include_path='.:/usr/local/lib/php')
in .../wp-content/plugins/fluent-smtp/vendor/composer/autoload_real.php:39

What seems to be going on

vendor/ is committed, but only the autoloader plumbing, which makes sense given composer.json has no runtime require section at all and only require-dev. Eight files are tracked:

vendor/autoload.php
vendor/composer/ClassLoader.php
vendor/composer/LICENSE
vendor/composer/autoload_{classmap,namespaces,psr4,real,static}.php

The committed vendor/composer/autoload_static.php carries a files entry:

public static $files = array (
    '9b38cf48e83f5d8f60375221cd213eee' => __DIR__ . '/..' . '/phpstan/phpstan/bootstrap.php',
);

Composer's files autoloads are eager rather than lazy, so they are required unconditionally on every request rather than when a class is first referenced. The load chain:

fluent-smtp.php:21            require_once .../boot.php
  boot.php:13                 require .../vendor/autoload.php
    vendor/autoload.php:22    ComposerAutoloaderInit...::getLoader()
      autoload_real.php:39    require $file;          <-- fatal, the file is not there

The same committed classmap also lists sixteen szepeviktor/phpstan-wordpress classes whose files are likewise absent, but those are harmless: classmap entries are lazy and nothing requests those classes at runtime. It is specifically the eager files entry that is fatal.

We reproduced the entry by running composer install with dev dependencies present against a copy of composer.json. The generated autoload_static.php contains the identical entry, hash included. It appears to have arrived with 7fd93b3b ("Register a void http_api_curl callback and regenerate the classmap"), which regenerated the autoloader on a machine that had dev dependencies installed.

Who this affects

Install path Affected
wordpress.org, or any release zip No
A zip built by build.sh No
A developer working copy where composer install has been run No
A git clone where composer has not been run Yes

Release users are fine because build.sh:79 runs composer install --no-dev --optimize-autoloader --classmap-authoritative before zipping, which regenerates the autoloader with an empty files array. build.sh:148 already fails the build if phpstan leaks into the zip.

It only shows up on a checkout where composer has not been run, which is the path someone takes when testing a branch or contributing.

Verified on

master at 78c462c, activated from a pristine clone:

WordPress PHP Result
6.9.8 8.3 fatal at autoload_real.php:39
6.8.9 8.1 fatal at autoload_real.php:39
6.8.9 7.4 fatal at autoload_real.php:39

Nothing about it looks version-specific, since the failure happens in the autoloader before any plugin or WordPress code runs.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions