{"record":{"id":"abf67272684c1695","repo":"yiisoft/yii2","slug":"ownership-must-be-an-integer-string-array-or-n","errorCode":null,"errorMessage":"$ownership must be an integer, string, array, or null.","messagePattern":"\\$ownership must be an integer, string, array, or null\\.","errorType":"exception","errorClass":"yii\\base\\InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"framework/helpers/BaseFileHelper.php","lineNumber":998,"sourceCode":"            return;\n        }\n\n        $user = $group = null;\n        if (!empty($ownership) || $ownership === 0 || $ownership === '0') {\n            if (is_int($ownership)) {\n                $user = $ownership;\n            } elseif (is_string($ownership)) {\n                $ownerParts = explode(':', $ownership);\n                $user = $ownerParts[0];\n                if (count($ownerParts) > 1) {\n                    $group = $ownerParts[1];\n                }\n            } elseif (is_array($ownership)) {\n                $ownershipIsIndexed = ArrayHelper::isIndexed($ownership);\n                $user = ArrayHelper::getValue($ownership, $ownershipIsIndexed ? 0 : 'user');\n                $group = ArrayHelper::getValue($ownership, $ownershipIsIndexed ? 1 : 'group');\n            } else {\n                throw new InvalidArgumentException('$ownership must be an integer, string, array, or null.');\n            }\n        }\n\n        if ($mode !== null) {\n            if (!is_int($mode)) {\n                throw new InvalidArgumentException('$mode must be an integer or null.');\n            }\n            if (!chmod($path, $mode)) {\n                throw new Exception('Unable to change mode of \"' . $path . '\" to \"0' . decoct($mode) . '\".');\n            }\n        }\n        if ($user !== null && $user !== '') {\n            if (is_numeric($user)) {\n                $user = (int) $user;\n            } elseif (!is_string($user)) {\n                throw new InvalidArgumentException('The user part of $ownership must be an integer, string, or null.');\n            }\n            if (!chown($path, $user)) {","sourceCodeStart":980,"sourceCodeEnd":1016,"githubUrl":"https://github.com/yiisoft/yii2/blob/66f00d18a29b520f85e8e8f1e32d1e7e7b556cac/framework/helpers/BaseFileHelper.php#L980-L1016","documentation":"changeOwnership() accepts $ownership only as int (uid), string ('user' or 'user:group'), array (indexed [user, group] or associative ['user' => ..., 'group' => ...]), or null; every other type falls into the final else branch and throws InvalidArgumentException. This is a pure type-contract violation — the filesystem was never touched.","triggerScenarios":"changeOwnership($path, 1000.5) with a float uid; passing a stdClass/stdClass-like config object; a boolean sneaking in because a config lookup defaulted to false; a float produced by arithmetic on an uid before the call.","commonSituations":"Ownership values coming from JSON/YAML config (nested objects instead of scalars) forwarded unchecked; dynamic values where a null-coalescing default yields a bool; values extracted from an API payload with unknown shape.","solutions":["Normalize to a supported scalar before calling: cast numeric uids to int or build a 'user:group' string yourself.","Validate the value first: is_int || is_string || is_array || is_null.","Fix the config source so ownership is a simple scalar like 'www-data:www-data'."],"exampleFix":"// before\n\\yii\\helpers\\FileHelper::changeOwnership($file, $config->owner); // $config->owner is \\stdClass\n\n// after\n$owner = is_array($config->owner)\n    ? implode(':', [$config->owner['user'] ?? '', $config->owner['group'] ?? ''])\n    : (string) $config->owner;\n\\yii\\helpers\\FileHelper::changeOwnership($file, $owner);","handlingStrategy":"type-guard","validationCode":"$ok = $ownership === null || is_int($ownership) || is_string($ownership) || is_array($ownership);\nif (!$ok) {\n    throw new \\InvalidArgumentException('$ownership must be int, string, array, or null');\n}","typeGuard":"/** @param mixed $ownership */\nfunction isOwnershipValue($ownership): bool\n{\n    return $ownership === null\n        || is_int($ownership)\n        || is_string($ownership)\n        || is_array($ownership);\n}","tryCatchPattern":null,"preventionTips":["Keep ownership config as a scalar string ('www-data:www-data') rather than structured values.","Validate values from JSON/YAML config before passing them to filesystem APIs.","Watch for boolean defaults from config lookups (?? false) leaking into typed parameters."],"tags":["ownership","type-validation","invalid-argument","yii2"],"backgroundTag":"wrong-argument-type","analyzedSha":"66f00d18a29b520f85e8e8f1e32d1e7e7b556cac","analyzedAt":"2026-08-17T05:17:23.470Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}