cakephp/cakephp · error · InvalidArgumentException
` ` is not a valid hook name. Must be one of ` .
Error message
`%s` is not a valid hook name. Must be one of `%s.`
What it means
Cake\Core\BasePlugin::checkHook() validates the $hook argument against static::VALID_HOOKS and throws InvalidArgumentException for anything else. It backs the plugin enable/disable/isEnabled API, so only hooks the plugin class declares as valid (typically 'bootstrap', 'routes', 'console', 'middleware', etc.) may be queried or toggled.
Solutions
- Use a hook name present in the plugin's VALID_HOOKS constant (check the concrete plugin class)
- Reference the constant directly instead of a literal: `$plugin->enable(BasePluginClass::VALID_HOOKS[0])` or a named constant
- Verify spelling/singular form of the hook string
- If you control the plugin, add the new hook to static::$hooks/VALID_HOOKS if it should be supported
Example fix
// before
$plugin->isEnabled('events'); // not a valid hook
// after
$plugin->isEnabled('bootstrap'); // one of static::VALID_HOOKS Defensive patterns
Strategy: validation
Validate before calling
if (!in_array($hook, SomePlugin::VALID_HOOKS, true)) {
return false; // or throw/with a clear message listing valid hooks
}
$enabled = $plugin->isEnabled($hook); Type guard
function isValidPluginHook(string $hook, string $pluginClass): bool {
return defined($pluginClass . '::VALID_HOOKS')
&& in_array($hook, $pluginClass::VALID_HOOKS, true);
} Try / catch
try {
$plugin->enable($hook);
} catch (\InvalidArgumentException $e) {
// log invalid hook name; fall back to a valid default
$plugin->enable('bootstrap');
} Prevention
- Always source hook names from the plugin's VALID_HOOKS constant, not string literals
- Centralize hook names in app-level constants
- Check plugin docs/changelog when upgrading for removed hooks
- Unit-test plugin bootstrap configuration
When it happens
Trigger: `$plugin->enable('hooks')`, `->disable('bootstrapx')`, `->isEnabled('service')` with a hook name not listed in the plugin class's VALID_HOOKS constant; typos or pluralization mistakes in the hook string; passing a hook a plugin subclass removed from its VALID_HOOKS.
Common situations: Configuration code enabling/disabling plugin features at bootstrap with hand-typed hook names; copy-pasted code between plugin classes with differing VALID_HOOKS; upgrading a plugin that removed or renamed hooks.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Argument 2 is expected to have a `repository` key that…
- Cannot add middleware group
- Cannot add ' ' middleware to group ' '. It has not been…
- Cannot use path tokens of type
- `CONFIG/plugins.php` not found or does not return an array
AI-assisted analysis of cakephp/cakephp@1128eba9b0 (2026-09-12).
Data as JSON: /api/errors/d35d11cc58936180.
Report an issue: GitHub.
Appendix: source
Thrown at src/Core/BasePlugin.php:257
*/
public function isEnabled(string $hook): bool
{
$this->checkHook($hook);
return $this->{"{$hook}Enabled"} === true;
}
/**
* Check if a hook name is valid
*
* @param string $hook The hook name to check
* @throws \InvalidArgumentException on invalid hooks
* @return void
*/
protected function checkHook(string $hook): void
{
if (!in_array($hook, static::VALID_HOOKS, true)) {
throw new InvalidArgumentException(sprintf(
'`%s` is not a valid hook name. Must be one of `%s.`',
$hook,
implode(', ', static::VALID_HOOKS),
));
}
}
/**
* @inheritDoc
*/
public function routes(RouteBuilder $routes): void
{
$path = $this->getConfigPath() . 'routes.php';
if (is_file($path)) {
$return = require $path;
if ($return instanceof Closure) {
$return($routes);
}View on GitHub (pinned to 1128eba9b0)