yiisoft/yii2 · error · yii\base\InvalidArgumentException
The user part of $ownership must be an integer, string, or n
Error message
The user part of $ownership must be an integer, string, or null.
What it means
Inside changeOwnership(), the extracted 'user' part must be numeric-coercible, a string, or null; an array or object (e.g. pulled out of the associative ownership array) hits the elseif !is_string branch and throws InvalidArgumentException before chown() is called. The defect is in how the ownership array/string was assembled, not in the environment.
Source
Thrown at framework/helpers/BaseFileHelper.php:1014
$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.');
}
if (!chgrp($path, $group)) {
throw new Exception('Unable to change group ownership of "' . $path . '" to "' . $group . '".');
}
}
}
}
View on GitHub (pinned to 66f00d18a2)
Solutions
- Flatten config to scalar user/group values ('user' => 'www-data').
- Validate the extracted user before the call: is_numeric($user) || is_string($user) || $user === null.
- Cast numeric strings to int and pass plain strings otherwise.
Example fix
// before \yii\helpers\FileHelper::changeOwnership($file, ['user' => ['name' => 'www-data']]); // after \yii\helpers\FileHelper::changeOwnership($file, ['user' => 'www-data']);
Defensive patterns
Strategy: type-guard
Validate before calling
$user = is_array($ownership) ? ($ownership['user'] ?? null) : $ownership;
if (!(is_numeric($user) || is_string($user) || $user === null)) {
throw new \InvalidArgumentException('Ownership user part must be scalar');
} Type guard
/** @param mixed $user */
function isUserPart($user): bool
{
return $user === null || $user === '' || is_numeric($user) || is_string($user);
} Prevention
- Flatten ownership config to scalar 'user' and 'group' values.
- Reject structured/nested ownership values at the config-loading boundary.
- Document the ownership parameter contract (int|string|array|null) wherever wrappers expose it.
When it happens
Trigger: ['user' => ['name' => 'www-data']] — a nested array under the 'user' key; ArrayHelper::getValue($ownership, 'user') returning an array default; indexed form [0 => ['uid' => 33], 1 => 33] where the user slot holds an array.
Common situations: YAML config producing nested maps for ownership; forwarding unchecked request/config data into the ownership argument; config schemas that allow both scalar and structured forms and default to the structured one.
Related errors
- $ownership must be an integer, string, array, or null.
- The group part of $ownership must be an integer, string or n
- Exclude/include pattern must be a string.
- Unable to change ownership, "{$path}" is not a file or direc
- $mode must be an integer or null.
AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17).
Data as JSON: /api/errors/2b1f544c237cb452.
Report an issue: GitHub.