{"record":{"id":"455cf98b5ea0687b","repo":"yiisoft/yii2","slug":"mode-must-be-an-integer-or-null","errorCode":null,"errorMessage":"$mode must be an integer or null.","messagePattern":"\\$mode must be an integer or null\\.","errorType":"exception","errorClass":"yii\\base\\InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"framework/helpers/BaseFileHelper.php","lineNumber":1004,"sourceCode":"                $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)) {\n                throw new Exception('Unable to change user ownership of \"' . $path . '\" to \"' . $user . '\".');\n            }\n        }\n        if ($group !== null && $group !== '') {\n            if (is_numeric($group)) {\n                $group = (int) $group;","sourceCodeStart":986,"sourceCodeEnd":1022,"githubUrl":"https://github.com/yiisoft/yii2/blob/66f00d18a29b520f85e8e8f1e32d1e7e7b556cac/framework/helpers/BaseFileHelper.php#L986-L1022","documentation":"changeOwnership() passes $mode straight to chmod(), which requires a PHP integer; strings like '0644' — the shell habit — fail is_int() and throw InvalidArgumentException before any filesystem call. PHP never auto-converts octal strings, and the octal-looking text is a string, so the API rejects it up front.","triggerScenarios":"FileHelper::changeOwnership($path, 'www-data', '0644'); a mode loaded from JSON/DB config, where values always arrive as strings; a mode computed as '0' . decoct($m) and not cast back; passing mode from a framework-agnostic config array shared with shell scripts.","commonSituations":"Config-driven permission settings where YAML parses 0644 as int but JSON keeps '0644' a string; porting shell snippets (chmod 0644 ...) to PHP; modes stored in environment variables.","solutions":["Use an octal integer literal: 0644, 0755 — never the quoted string form.","Cast config strings with base 8: $mode = intval($config['mode'], 8);","Validate before calling: is_int($mode), or is_string($mode) && ctype_digit($mode) followed by an intval(..., 8) cast."],"exampleFix":"// before\n\\yii\\helpers\\FileHelper::changeOwnership($file, 'www-data', '0755');\n\n// after\n$mode = intval('0755', 8); // int 493\n\\yii\\helpers\\FileHelper::changeOwnership($file, 'www-data', $mode);","handlingStrategy":"type-guard","validationCode":"if (is_string($mode)) {\n    $mode = intval($mode, 8); // '0644' → 420\n}\nif (!is_int($mode)) {\n    throw new \\InvalidArgumentException('Mode must be an octal int, e.g. 0644');\n}\n\\yii\\helpers\\FileHelper::changeOwnership($path, 'www-data', $mode);","typeGuard":"/** @param mixed $mode */\nfunction isModeValue($mode): bool\n{\n    return $mode === null || is_int($mode) || (is_string($mode) && ctype_digit($mode));\n}","tryCatchPattern":null,"preventionTips":["Use octal integer literals (0644) in PHP, never quoted strings.","Cast modes from config/DB with intval($value, 8).","Remember JSON stores numbers as strings when quoted — validate config schemas for numeric modes."],"tags":["permissions","chmod","type-validation","octal","yii2"],"backgroundTag":"wrong-argument-type","analyzedSha":"66f00d18a29b520f85e8e8f1e32d1e7e7b556cac","analyzedAt":"2026-08-17T05:17:23.470Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}