yiisoft/yii2 · error · ForbiddenHttpException
You are not allowed to perform this action.
Error message
You are not allowed to perform this action.
What it means
yii\filters\AccessControl::denyAccess() runs when no access rule matched the request with allow=true. If the current user is a guest it calls loginRequired() (redirect to login), but for an authenticated user - or when the User component is detached ($user === false) - it throws ForbiddenHttpException with 'You are not allowed to perform this action.', which Yii renders as HTTP 403.
Source
Thrown at framework/filters/AccessControl.php:159
$this->denyAccess($user);
}
return false;
}
/**
* Denies the access of the user.
* The default implementation will redirect the user to the login page if he is a guest;
* if the user is already logged, a 403 HTTP exception will be thrown.
* @param User|false $user the current user or boolean `false` in case of detached User component
* @throws ForbiddenHttpException if the user is already logged in or in case of detached User component.
*/
protected function denyAccess($user)
{
if ($user !== false && $user->getIsGuest()) {
$user->loginRequired();
} else {
throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
}
}
}
View on GitHub (pinned to 66f00d18a2)
Solutions
- Adjust the rules so legitimate users match: add the user's role to 'roles', fix the 'verbs'/'ips'/'matchCallback' condition.
- Assign the required RBAC permission to the role/user (auth manager assignment migration).
- For stateless APIs, configure AccessControl with 'user' => false knowingly and return 401 semantics yourself, or use yii\filters\auth\HttpHeaderAuth instead.
- Override denyAccess() in a custom AccessControl subclass to redirect or return JSON instead of a bare 403.
Example fix
// before - logged-in non-admins get 403
'access' => [
'class' => AccessControl::class,
'only' => ['delete'],
'rules' => [['actions' => ['delete'], 'allow' => true, 'roles' => ['admin']]],
],
// after - also allow editors, deny everyone else explicitly
'access' => [
'class' => AccessControl::class,
'only' => ['delete'],
'rules' => [
['actions' => ['delete'], 'allow' => true, 'roles' => ['admin', 'editor']],
['allow' => false],
],
], Defensive patterns
Strategy: validation
Validate before calling
// Before performing a restricted action, check the same rule data AccessControl uses
if (!Yii::$app->user->can('deletePost')) {
throw new \yii\web\ForbiddenHttpException('You are not allowed to perform this action.');
}
// or probe the filter configuration before running the action
foreach ($this->getBehavior('access')->rules as $rule) {
if ($rule->allows(Yii::$app->controller->action, Yii::$app->user, Yii::$app->request) !== false) {
$allowed = true; break;
}
} Try / catch
use yii\web\ForbiddenHttpException;
try {
return $this->runAction('delete');
} catch (ForbiddenHttpException $e) {
Yii::$app->session->setFlash('error', 'Insufficient permissions.');
return $this->redirect(['index']);
} Prevention
- End every AccessControl rule set with an explicit ['allow' => false] fallback so denial is intentional, not accidental.
- Add an RBAC assignment migration whenever a new permission appears in rules, and run it in the same deploy.
- Cover access rules with functional tests per role (guest, editor, admin) so missing roles surface in CI.
- For stateless APIs set 'user' => false deliberately and return 401-style responses before AccessControl denies.
When it happens
Trigger: An action covered by AccessControl's 'only'/'except' list where every rule evaluates false for a logged-in user: roles that the user lacks, 'matchCallback' returning false, verbs/IPs not matching; or a controller using AccessControl in an app where the 'user' component is disabled (user => false).
Common situations: RBAC permission not assigned to the user's role (only ['admin'] while user is 'editor'); matchCallback logic bugs (wrong comparison, inverted condition); forgetting that guests get a login redirect only when the User component exists - stateless APIs with a detached user always get 403; deploying new access rules before migrating auth assignments.
Related errors
- Unknown scenario: $scenario
- Invalid validation rule: a rule must specify both attribute
- The directory does not exist: $path
- Controller class must extend from \yii\base\Controller.
- Unable to determine the entry script file path.
AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17).
Data as JSON: /api/errors/2df8b80d57ada763.
Report an issue: GitHub.