Composer依赖更新报错:Filesystem::isAbsolutePath参数为null求助
TypeError: Argument #1 ($path) must be of type string, null given in drupal-composer/preserve-paths
我在更新项目依赖包时,Composer进程崩溃,报错如下:
[TypeError]
Composer\Util\Filesystem::isAbsolutePath(): Argument #1 ($path) must be of type string, null given, called in /path/to/project/folder/vendor/drupal-composer/preserve-paths/src/PluginWrapper.php on line 190.
我的composer.json内容:
{ "name": "zebralab/drupal-8", "description": "ZebraLab (Drupal 8) site.", "type": "project", "license": "GPL-2.0+", "repositories": { "lenient": { "type": "composer", "url": "https://packages.drupal.org/lenient" }, "drupal-8": { "type": "composer", "url": "https://packages.drupal.org/8" }, "drupal-typed_data_explorer": { "type": "package", "package": { "type": "drupal-module", "name": "drupal/typed_data_explorer", "description": "Discover Typed Data API for Drupal. For more details, see http://lussoluca.github.io/DDD-2016/#/ .", "version": "1.0.0", "dist": { "url": "https://github.com/wellnet/typed_data_explorer/archive/master.zip", "type": "zip" } } } }, "require": { "php": ">=8.1", "composer-plugin-api": "^2.0", "composer/installers": "^2", "cweagans/composer-patches": "^1.6", "davidbarratt/custom-installer": "^1.1", "drupal-composer/preserve-paths": "^0.1.6", "drupal/admin_toolbar": "^3.1", "drupal/auto_entitylabel": "^3.0", "drupal/better_exposed_filters": "^6.0.3", "drupal/blazy": "^2.5", "drupal/block_class": "^2.0.11", "drupal/block_field": "1.x.dev", "drupal/block_visibility_groups": "^2.0.1", "drupal/ckeditor_indentblock": "^1.0@beta", "drupal/ckeditor_media_embed": "^1.0", "drupal/classy_paragraphs": "^1.0@beta", "drupal/config_filter": "^2.6.0", "drupal/config_split": "^2.0.0", "drupal/config_update": "^2.0@alpha", "drupal/contact_block": "^2.0.2", "drupal/core-composer-scaffold": "^10", "drupal/core-project-message": "^10", "drupal/core-recommended": "^10", "drupal/ctools": "^4.0.4", "drupal/devel": "^5.1.2", "drupal/dropzonejs": "^2.5", "drupal/ds": "^3.1", "drupal/editor_advanced_link": "^2.0", "drupal/editor_file": "^2.0@RC", "drupal/entity_browser": "^2.10.0", "drupal/entity_embed": "~1.0-beta2", "drupal/facets": "^2.0.6", "drupal/features": "^3.14", "drupal/field_group": "^3.1", "drupal/file_browser": "~1.1", "drupal/filebrowser": "^3 || ^3.1@RC", "drupal/geolocation": "^3.7", "drupal/google_tag": "^2.0.4", "drupal/iframe": "^2.15", "drupal/image_link_attributes": "~1.0", "drupal/lang_dropdown": "^2.1", "drupal/link_class": "^2", "drupal/maxlength": "^2.1", "drupal/metatag": "^2.0.0", "drupal/paragraphs": "^1.1", "drupal/recaptcha": "^3.0", "drupal/search_api": "^1.3", "drupal/slick": "^2.4", "drupal/slick_extras": "~1.0-beta2", "drupal/slick_views": "^2.0", "drupal/smtp": "~1.0-beta3", "drupal/telephone_validation": "^2.3", "drupal/token": "^1.0@RC", "drupal/token_filter": "^2.1.0", "drupal/transliterate_filenames": "^2.0.2", "drupal/typed_data_explorer": "^1.0", "drupal/video_embed_field": "^2.4", "drupal/views_ajax_history": "^1.5", "drupal/views_infinite_scroll": "^2.0", "drupal/views_slideshow": "^5.0.0", "drush/config-extra": "^1.0", "giggsey/libphonenumber-for-php": "^8.12", "mglaman/composer-drupal-lenient": "^1.0", "symfony/filesystem": "^6.4", "symfony/finder": "^6.4", "webflo/drupal-finder": "^1.0.0", "webmozart/path-util": "^2.3", "wikimedia/composer-merge-plugin": "^2" }, "require-dev": { "behat/mink": "^1.11", "behat/mink-browserkit-driver": "^2.2", "drupal/core-dev": "^10", "drupal/pathauto": "^1.8", "symfony/css-selector": "^6.4" }, "conflict": { "drupal/drupal": "*" }, "minimum-stability": "dev", "prefer-stable": true, "config": { "preferred-install": "dist", "autoloader-suffix": "Drupal8", "sort-packages": true, "allow-plugins": { "composer/installers": true, "dealerdirect/phpcodesniffer-composer-installer": true, "drupal/console-extend-plugin": true, "cweagans/composer-patches": true, "davidbarratt/custom-installer": true, "drupal/core-composer-scaffold": true, "drupal/core-project-message": true, "wikimedia/composer-merge-plugin": true, "mglaman/composer-drupal-lenient": true, "php-http/discovery": true, "phpstan/extension-installer": true, "drupal-composer/preserve-paths": true } }, "autoload": { "classmap": [ "scripts/composer/ScriptHandler.php" ] }, "scripts": { "drupal-scaffold": "DrupalComposer\DrupalScaffold\Plugin::scaffold", "pre-install-cmd": ["DrupalProject\composer\ScriptHandler::checkComposerVersion"], "pre-update-cmd": ["DrupalProject\composer\ScriptHandler::checkComposerVersion"], "post-install-cmd": ["DrupalProject\composer\ScriptHandler::createRequiredFiles"], "post-update-cmd": [ "DrupalProject\composer\ScriptHandler::createRequiredFiles", "git add ." ] }, "extra": { "_readme": [ "By default Drupal loads the autoloader from ./vendor/autoload.php.", "To change the autoloader you can edit ./autoload.php.", "This file specifies the packages.drupal.org repository.", "You can read more about this composer repository at:", "https://www.drupal.org/node/2718229" ], "drupal-scaffold": { "excludes": [ ".editorconfig", ".editorconfig", ".gitattributes", ".gitignore", "robots.txt" ], "omit-defaults": false }, "installer-paths": { "core": ["type:drupal-core"], "libraries/{$name}": ["type:drupal-library"], "modules/contrib/{$name}": ["type:drupal-module"], "modules/custom/{$name}": ["type:drupal-custom-module"], "profiles/contrib/{$name}": ["type:drupal-profile"], "profiles/custom/{$name}": ["type:drupal-custom-profile"], "themes/contrib/{$name}": ["type:drupal-theme"], "themes/custom/{$name}": ["type:drupal-custom-theme"], "drush/contrib/{$name}": ["type:drupal-drush"], "drush/custom/{$name}": ["type:drupal-custom-drush"] }, "preserve-paths": [ "./modules", "./profiles", "./sites", "./themes" ], "enable-patching": true, "patches-ignore": { }, "patches-file": "composer.patches.json" } }
我已经搜索过该错误信息、drupal-composer/preserve-paths相关错误,也在Drupal论坛提问过,但没找到解决办法。
问题根源
- 版本不兼容:你使用的
drupal-composer/preserve-paths版本是^0.1.6,这个版本非常老旧,没有适配PHP 8.1的严格类型检查机制。PHP 8+对函数参数类型要求严格,当插件内部逻辑产生null值并传递给Composer\Util\Filesystem::isAbsolutePath()时,就会触发这个TypeError。 - 路径处理逻辑缺陷:旧版本插件在处理
preserve-paths配置中的路径时,可能因为路径不存在、权限问题或内部逻辑漏洞,导致获取到null路径值,进而触发参数类型错误。
解决方案
方案1:升级drupal-composer/preserve-paths到兼容版本
执行以下命令升级插件到最新可用版本:
composer require drupal-composer/preserve-paths:^0.1.15 --no-update composer update drupal-composer/preserve-paths --with-all-dependencies
最新的0.1.x版本已经修复了PHP 8.x的类型兼容问题,能解决这个报错。
方案2:替换为composer/installers的原生路径保留功能
composer/installers从2.0版本开始已经原生支持路径保留,不需要依赖单独的preserve-paths插件,步骤如下:
- 移除旧插件:
composer remove drupal-composer/preserve-paths
- 在
composer.json的extra字段中,将preserve-paths配置移到installer-paths同级的位置,保持原有路径列表不变:
"extra": { // ... 其他配置 "installer-paths": { // ... 原有路径配置 }, "preserve-paths": [ "./modules", "./profiles", "./sites", "./themes" ], // ... 其他配置 }
- 执行更新命令:
composer update
方案3:临时禁用插件完成更新(紧急情况)
如果上述方案暂时无法执行,可以临时禁用插件来完成依赖更新:
- 在
composer.json的config.allow-plugins中,将drupal-composer/preserve-paths设为false:
"config": { "allow-plugins": { // ... 其他插件 "drupal-composer/preserve-paths": false } }
- 执行更新:
composer update
- 更新完成后,再恢复插件启用状态,或按方案1/2替换插件。
内容的提问来源于stack exchange,提问作者Dmitry Shepelenko
相关产品推荐
相关产品推荐

