phalcon/cphalcon · error · Phalcon\Auth\Exceptions\AccessDenied
Access denied for {type} '{name}'
Error message
Access denied for {type} '{name}' What it means
The Auth dispatcher listener enforces access via an access gate (e.g. Phalcon\Auth\Access\Acl). When the gate denies an action, the listener first tries to recover by forwarding to a redirect target; only if no forward handler is available or the access policy exposes no redirectTo() does it throw AccessDenied labelled with the action type ('task', 'action', 'route') and the action name. It is the terminal signal that a request was refused and no graceful redirect was configured.
Source
Thrown at phalcon/Auth/AbstractAuthDispatcherListener.zep:80
let access = this->manager->getAccess();
if (access === null) {
return true;
}
if (access->isAllowed(this->manager->guard(), actionName, context)) {
return true;
}
if (forwardHandler !== null) {
let target = access->redirectTo();
if (target !== null) {
{forwardHandler}(target);
return false;
}
}
throw new AccessDenied(this->getActionType(), actionName);
}
/**
* Returns the kind label used by AccessDenied (e.g. 'task', 'action',
* 'route').
*/
abstract protected function getActionType() -> string;
}
View on GitHub (pinned to b7419de9cd)
Solutions
- Grant access: add the matching `$acl->allow($role, $component, $action)` rule or assign the user the required role
- Configure graceful denial: set redirectTo() on the access policy and pass a forward handler to enforce() so refusals forward (e.g. to login) instead of throwing
- Whitelist genuinely public actions in the access policy's exceptActions
Example fix
// before: denial throws
$this->enforce('index', $context, null);
// after: denial forwards to login
$this->enforce('index', $context, function (array $target) {
$this->dispatcher->forward(['controller' => 'session', 'action' => 'login']);
});
// plus in the access policy: protected function redirectTo(): ?array { return ['controller' => 'session', 'action' => 'login']; } Defensive patterns
Strategy: try-catch
Validate before calling
if (!$acl->isAllowed($user->getRoleName(), $component, $actionName)) {
$response->redirect('/login')->send();
return;
} Try / catch
try {
$dispatcher->dispatch();
} catch (\Phalcon\Auth\Exceptions\AccessDenied $e) {
$logger->notice('Access denied: ' . $e->getMessage());
$response->setStatusCode(403)->setContent('Forbidden')->send();
} Prevention
- Always configure redirectTo() on access policies and pass a forward handler to enforce() so denials redirect rather than throw
- Keep ACL rules per role/component/action in config reviewed alongside new routes
- List public actions in exceptActions explicitly instead of relying on deny-all + exception handling
When it happens
Trigger: `$listener->enforce($actionName, $context, $forwardHandler)` (or the dispatcher event that calls it) where the gate's isAllowed() returns false and either forwardHandler is null or the access object's redirectTo() returns null.
Common situations: Wiring the new Phalcon Auth component without configuring a redirect for denied users; ACL rules missing an allow entry for the user's role; forgetting to add a public action to the access policy's exceptActions.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- The Acl access gate requires the 'handler' context key to de
- Authenticated user does not implement 'Phalcon\Acl\RoleAware
- Access '{accessName}' is not registered
- Malformed ACL snapshot structure
- The role name cannot be '*'
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/a21f50f4d109ba3e.
Report an issue: GitHub.