yiisoft/yii2 · error · yii\base\Exception
Unable to change mode of "{$path}" to "0{$mode}".
Error message
Unable to change mode of "{$path}" to "0{$mode}". What it means
After validating that $mode is an int, changeOwnership() calls chmod($path, $mode) and converts a false return into yii\base\Exception with the target path and octal mode in the message. Unlike the argument errors, this is an environment/privilege failure: the running PHP process is not the file's owner (and not root), the filesystem is read-only, or a policy (SELinux, mount options) blocks the change.
Source
Thrown at framework/helpers/BaseFileHelper.php:1007
$user = $ownerParts[0];
if (count($ownerParts) > 1) {
$group = $ownerParts[1];
}
} elseif (is_array($ownership)) {
$ownershipIsIndexed = ArrayHelper::isIndexed($ownership);
$user = ArrayHelper::getValue($ownership, $ownershipIsIndexed ? 0 : 'user');
$group = ArrayHelper::getValue($ownership, $ownershipIsIndexed ? 1 : 'group');
} else {
throw new InvalidArgumentException('$ownership must be an integer, string, array, or null.');
}
}
if ($mode !== null) {
if (!is_int($mode)) {
throw new InvalidArgumentException('$mode must be an integer or null.');
}
if (!chmod($path, $mode)) {
throw new Exception('Unable to change mode of "' . $path . '" to "0' . decoct($mode) . '".');
}
}
if ($user !== null && $user !== '') {
if (is_numeric($user)) {
$user = (int) $user;
} elseif (!is_string($user)) {
throw new InvalidArgumentException('The user part of $ownership must be an integer, string, or null.');
}
if (!chown($path, $user)) {
throw new Exception('Unable to change user ownership of "' . $path . '" to "' . $user . '".');
}
}
if ($group !== null && $group !== '') {
if (is_numeric($group)) {
$group = (int) $group;
} elseif (!is_string($group)) {
throw new InvalidArgumentException('The group part of $ownership must be an integer, string or null.');
}View on GitHub (pinned to 66f00d18a2)
Solutions
- Run the permission change as the file's owner (or root) — move it to the deploy script/entrypoint instead of application code.
- Ensure files are created by the same user that will later chmod them.
- Verify the filesystem supports Unix modes and is mounted rw (mount | grep <path>).
- Catch yii\base\Exception and fail loudly with path and mode in the log rather than ignoring it.
Example fix
// before: runs as www-data, file owned by deployer — chmod fails
\yii\helpers\FileHelper::changeOwnership(\Yii::getAlias('@app/runtime/app.log'), null, 0644);
// after: perform in deploy step as the owner
# deploy.sh (runs as deployer, file owner)
yii fix-perms/apply Defensive patterns
Strategy: try-catch
Validate before calling
// cheap pre-flight: can this process modify the node at all?
if (!is_writable($path)) {
throw new \RuntimeException("Not permitted to chmod: {$path}");
}
\yii\helpers\FileHelper::changeOwnership($path, null, 0644); Try / catch
try {
\yii\helpers\FileHelper::changeOwnership($path, null, 0644);
} catch (\yii\base\Exception $e) {
// environment failure — report, don't swallow
\Yii::error("chmod failed: {$e->getMessage()}", 'files');
throw new \RuntimeException('Permission fixup failed; run the deploy fix-perms step.', 0, $e);
} Prevention
- Create files with the correct mode at creation time (fopen/mkdir mode) so chmod fixups are rarely needed.
- Do permission changes as the file owner in the deploy pipeline, not as the web user at runtime.
- Verify filesystems are mounted rw and support POSIX modes before shipping container setups.
- Alert on chmod failures — silent skips hide ownership drift.
When it happens
Trigger: The web server user (www-data/apache) chmod-ing files created by the deploy user; chmod on a read-only volume or a bind-mount with ro flag; SELinux/AppArmor denying mode changes; FAT/exFAT/NTFS mounts that do not support Unix permission bits.
Common situations: Post-deploy fixup steps executed in a web request instead of the deploy pipeline; containers with read-only layers or dropped capabilities; files created by a root CLI script later touched by the web user; Docker volumes mounted from Windows hosts.
Related errors
- $mode must be an integer or null.
- Unable to change user ownership of "{$path}" to "{$user}".
- Unable to change group ownership of "{$path}" to "{$group}".
- Failed to change permissions for directory "{$path}": {messa
- MemCache requires PHP $extension extension to be loaded.
AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17).
Data as JSON: /api/errors/49cbeee2580149fb.
Report an issue: GitHub.