getgrav/grav · error · LogicException
User class was called too early!
Error message
User class was called too early!
What it means
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.
Source
Thrown at system/src/Grav/Common/User/User.php:19
<?php
/**
* @package Grav\Common\User
*
* @copyright Copyright (c) 2015 - 2026 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\User;
use Grav\Common\Grav;
use Grav\Common\User\DataUser;
use Grav\Common\Flex;
use Grav\Common\User\Interfaces\UserCollectionInterface;
use Grav\Common\User\Interfaces\UserInterface;
if (!defined('GRAV_USER_INSTANCE')) {
throw new \LogicException('User class was called too early!');
}
if (defined('GRAV_USER_INSTANCE') && GRAV_USER_INSTANCE === 'FLEX') {
/**
* @deprecated 1.6 Use $grav['accounts'] instead of static calls. In type hints, please use UserInterface.
*/
class User extends Flex\Types\Users\UserObject
{
/**
* Load user account.
*
* Always creates user object. To check if user exists, use $this->exists().
*
* @param string $username
* @return UserInterface
* @deprecated 1.6 Use $grav['accounts']->load(...) instead.
*/
public static function load($username)View on GitHub (pinned to 6040efed04)
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.
Example fix
// before (standalone script)
require 'vendor/autoload.php';
$user = \Grav\Common\User\User::load('joe'); // LogicException: called too early
// after
require 'vendor/autoload.php';
// boot Grav exactly like index.php / bin/grav do (loader + container + init)
$grav = \Grav\Common\Grav::instance(['loader' => require 'vendor/autoload.php']);
// ... bootstrap ...
$user = $grav['accounts']->load('joe'); Defensive patterns
Strategy: validation
Validate before calling
if (!defined('GRAV_USER_INSTANCE')) {
// Grav is not bootstrapped: boot it (see index.php) or exit with a clear message
fwrite(STDERR, "Boot Grav before using user classes.\n");
exit(1);
}
$class = \Grav\Common\User\User::class; Type guard
function gravIsBootstrapped(): bool
{
return defined('GRAV_USER_INSTANCE');
} Try / catch
try {
$user = \Grav\Common\User\User::load('joe');
} catch (\LogicException $e) {
// class shim loaded pre-boot: bootstrap Grav and retry, or fix call ordering
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Invalid arguments, expected DOMElement or DOMDocument
- Invalid arguments, expected DOMElement or DOMDocument
- Setup: Configuration reload loop detected!
- Configuration is missing streams.schemes!
- Configuration is missing keys %s from streams.schemes!
AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17).
Data as JSON: /api/errors/afaba462d9455d0d.
Report an issue: GitHub.