yiisoft/yii2 · error · yii\base\InvalidArgumentException

The group part of $ownership must be an integer, string or n

Error message

The group part of $ownership must be an integer, string or null.

What it means

The mirror of the user-side check inside changeOwnership(): the extracted 'group' part must be numeric-coercible, a string, or null. An array or object in the group slot throws InvalidArgumentException before chgrp() runs. It reports a malformed ownership argument, not a filesystem failure.

Source

Thrown at framework/helpers/BaseFileHelper.php:1024

            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

  1. Flatten config so 'group' maps to a scalar (name or gid).
  2. Validate the extracted group: is_numeric($group) || is_string($group) || $group === null.
  3. Cast numeric strings to int before the call.

Example fix

// before
\yii\helpers\FileHelper::changeOwnership($file, ['user' => 'www-data', 'group' => ['gid' => 33]]);

// after
\yii\helpers\FileHelper::changeOwnership($file, ['user' => 'www-data', 'group' => 33]);
Defensive patterns

Strategy: type-guard

Validate before calling

$group = is_array($ownership) ? ($ownership['group'] ?? null) : null;
if (!(is_numeric($group) || is_string($group) || $group === null)) {
    throw new \InvalidArgumentException('Ownership group part must be scalar');
}

Type guard

/** @param mixed $group */
function isGroupPart($group): bool
{
    return $group === null || $group === '' || is_numeric($group) || is_string($group);
}

Prevention

When it happens

Trigger: ['group' => ['gid' => 33]]; the string form 'user:' combined with a downstream lookup that injects an array; indexed form [0 => 'www-data', 1 => ['gid' => 33]] with an array in the group slot.

Common situations: Structured config (YAML maps) for group ownership; ownership values merged from multiple config sources where one side supplies an array; API-driven ownership data with unknown shape.

Related errors


AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17). Data as JSON: /api/errors/176ba9395aa277ad. Report an issue: GitHub.