composer/composer · error · PluginBlockedException
contains a Composer plugin which is blocked by your…
Error message
{package}{global_suffix} contains a Composer plugin which is blocked by your allow-plugins config. You may add it to the list if you consider it safe.
You can run "composer {global_prefix}config --no-plugins allow-plugins.{package} [true|false]" to enable it (true) or disable it explicitly and suppress this exception (false)
See https://getcomposer.org/allow-plugins What it means
Thrown by PluginManager as a PluginBlockedException when a Composer plugin package is not explicitly allowed (or disallowed) in the 'config.allow-plugins' map of composer.json and the user did not authorize it interactively (or the session is non-interactive). Since Composer 2.2 plugins run only when whitelisted, to prevent arbitrary code execution from dependencies. The message tells you exactly how to allow or block it via config.
Solutions
- Run the exact command from the message: composer config --no-plugins allow-plugins.<package> true to allow it (or false to suppress).
- For global plugins, prefix with 'global': composer global config --no-plugins allow-plugins.<package> true.
- Add the full allow-plugins map to composer.json config and commit it so CI is reproducible.
- In CI, ensure the runner is non-interactive only AFTER allow-plugins is configured, or set COMPOSER_NO_INTERACTION=1 after committing the list.
Example fix
// before
{ "config": {} }
// after
{
"config": {
"allow-plugins": {
"phpstan/extension-installer": true,
"dealerdirect/phpcodesniffer-composer-installer": true
}
}
} Defensive patterns
Strategy: validation
Validate before calling
// Pre-check allow-plugins config before running install in CI
$pkg = 'phpstan/extension-installer';
$cfg = json_decode(file_get_contents('composer.json'), true);
$allowed = $cfg['config']['allow-plugins'] ?? [];
if (!array_key_exists($pkg, $allowed)) {
// explicitly allow or disallow to avoid the interactive block
$cfg['config']['allow-plugins'][$pkg] = true;
file_put_contents('composer.json', json_encode($cfg, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES));
} Type guard
function pluginIsDecided(string $pkg, array $config): bool {
return array_key_exists($pkg, $config['config']['allow-plugins'] ?? []);
} Try / catch
try {
// run composer operation
} catch (\Composer\Plugin\PluginBlockedException $e) {
// parse package name, prompt user, then run the suggested config command
throw $e;
} Prevention
- Commit an explicit 'allow-plugins' map in composer.json for every plugin you use.
- Run 'composer install' once interactively after adding a plugin dependency to seed the config.
- In CI set --no-interaction only after the allow-plugins map is committed.
When it happens
Trigger: During dependency resolution/install, PluginManager::arePluginsAllowed() finds the package missing from allow-plugins; the interactive prompt (y/n/d/?) either was never shown (non-interactive) or the user exhausted attempts. Reached via PluginManager::loadRepository() / registerPackage() when a package provides Composer\Plugin\PluginInterface.
Common situations: Upgrading to Composer 2.2+ where allow-plugins is required; CI runs (non-interactive) where a new plugin dependency triggers the block; a fresh 'composer require' of a package that ships a plugin (e.g. composer-require-fixer, phpstan/extension-installer).
Related errors
- Could not parse the value of '$key
- Invalid value for 'bin-compat
- Invalid value for COMPOSER_AUDIT_ABANDONED
- Repository type is not registered
- " " is an invalid value
AI-assisted analysis of composer/composer@c435d285c9 (2026-08-07).
Data as JSON: /api/errors/4f6690f7c1df141f.
Report an issue: GitHub.
Appendix: source
Thrown at src/Composer/Plugin/PluginManager.php:821
return $allow;
case '?':
default:
$attempts++;
$this->io->writeError([
'y - add package to allow-plugins in composer.json and let it run immediately',
'n - add package (as disallowed) to allow-plugins in composer.json to suppress further prompts',
'd - discard this, do not change composer.json and do not allow the plugin to run',
'? - print help',
]);
break;
}
}
} elseif ($optional) {
return false;
}
throw new PluginBlockedException(
$package.($isGlobalPlugin || $this->runningInGlobalDir ? ' (installed globally)' : '').' contains a Composer plugin which is blocked by your allow-plugins config. You may add it to the list if you consider it safe.'.PHP_EOL.
'You can run "composer '.($isGlobalPlugin || $this->runningInGlobalDir ? 'global ' : '').'config --no-plugins allow-plugins.'.$package.' [true|false]" to enable it (true) or disable it explicitly and suppress this exception (false)'.PHP_EOL.
'See https://getcomposer.org/allow-plugins'
);
}
}
View on GitHub (pinned to c435d285c9)