{"record":{"id":"afaba462d9455d0d","repo":"getgrav/grav","slug":"user-class-was-called-too-early","errorCode":null,"errorMessage":"User class was called too early!","messagePattern":"User class was called too early!","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"system/src/Grav/Common/User/User.php","lineNumber":19,"sourceCode":"<?php\n\n/**\n * @package    Grav\\Common\\User\n *\n * @copyright  Copyright (c) 2015 - 2026 Trilby Media, LLC. All rights reserved.\n * @license    MIT License; see LICENSE file for details.\n */\n\nnamespace Grav\\Common\\User;\n\nuse Grav\\Common\\Grav;\nuse Grav\\Common\\User\\DataUser;\nuse Grav\\Common\\Flex;\nuse Grav\\Common\\User\\Interfaces\\UserCollectionInterface;\nuse Grav\\Common\\User\\Interfaces\\UserInterface;\n\nif (!defined('GRAV_USER_INSTANCE')) {\n    throw new \\LogicException('User class was called too early!');\n}\n\nif (defined('GRAV_USER_INSTANCE') && GRAV_USER_INSTANCE === 'FLEX') {\n    /**\n     * @deprecated 1.6 Use $grav['accounts'] instead of static calls. In type hints, please use UserInterface.\n     */\n    class User extends Flex\\Types\\Users\\UserObject\n    {\n        /**\n         * Load user account.\n         *\n         * Always creates user object. To check if user exists, use $this->exists().\n         *\n         * @param string $username\n         * @return UserInterface\n         * @deprecated 1.6 Use $grav['accounts']->load(...) instead.\n         */\n        public static function load($username)","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/getgrav/grav/blob/6040efed04efa69b8209448ed81308e7c24147c2/system/src/Grav/Common/User/User.php#L1-L37","documentation":"Grav\\Common\\User\\User is a shim whose actual parent class (Flex UserObject vs DataUser User) is chosen at file-load time from the GRAV_USER_INSTANCE constant, defined during Grav bootstrap from the accounts configuration. The guard at line 19 throws a LogicException if the file gets autoloaded before the constant exists, preventing the wrong class hierarchy from being compiled.","triggerScenarios":"Referencing Grav\\Common\\User\\User (User::load(), instanceof, static calls) from code that runs with the autoloader but without a booted Grav: standalone CLI scripts that just require vendor/autoload.php, PHPUnit tests, or logic triggered during composer autoload-time events.","commonSituations":"Unit tests requiring the autoloader but never booting Grav; custom entry points using grav's vendor/autoload.php directly; plugin code executed outside the normal Grav request lifecycle.","solutions":["Do not touch the User shim directly — use $grav['accounts'] (UserCollectionInterface) or type-hint UserInterface after Grav is booted.","In scripts/tests, run the standard Grav bootstrap (as index.php / bin/grav do) so GRAV_USER_INSTANCE is defined before the class is first loaded.","Move logic that needs user classes into plugin hooks (onPluginsInitialized or later) instead of autoload-time code."],"exampleFix":"// before (standalone script)\nrequire 'vendor/autoload.php';\n$user = \\Grav\\Common\\User\\User::load('joe'); // LogicException: called too early\n\n// after\nrequire 'vendor/autoload.php';\n// boot Grav exactly like index.php / bin/grav do (loader + container + init)\n$grav = \\Grav\\Common\\Grav::instance(['loader' => require 'vendor/autoload.php']);\n// ... bootstrap ...\n$user = $grav['accounts']->load('joe');","handlingStrategy":"validation","validationCode":"if (!defined('GRAV_USER_INSTANCE')) {\n    // Grav is not bootstrapped: boot it (see index.php) or exit with a clear message\n    fwrite(STDERR, \"Boot Grav before using user classes.\\n\");\n    exit(1);\n}\n$class = \\Grav\\Common\\User\\User::class;","typeGuard":"function gravIsBootstrapped(): bool\n{\n    return defined('GRAV_USER_INSTANCE');\n}","tryCatchPattern":"try {\n    $user = \\Grav\\Common\\User\\User::load('joe');\n} catch (\\LogicException $e) {\n    // class shim loaded pre-boot: bootstrap Grav and retry, or fix call ordering\n}","preventionTips":["Prefer $grav['accounts'] and UserInterface over the static User shim.","In CLI/tests, run the standard Grav bootstrap before touching user classes.","Never reference Grav classes from composer autoload-time callbacks."],"tags":["bootstrap","user-management","load-order","php","class-loading"],"backgroundTag":"framework-not-bootstrapped","analyzedSha":"6040efed04efa69b8209448ed81308e7c24147c2","analyzedAt":"2026-08-17T05:07:31.593Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}