getgrav/grav · error · InvalidArgumentException

%s: Relationship %s does not exist

Error message

%s: Relationship %s does not exist

What it means

The Flex user object's relationship lookup (UserObject.php:727) only resolves two built-in relationships: 'media' (a list of buildMediaObject entries) and 'avatar'. Any other name falls through the switch to an InvalidArgumentException formatted as '%s: Relationship %s does not exist'. It signals that the requested relation name is not part of the user flex type's schema — unlike pages or other flex types, users expose no other relations.

Source

Thrown at system/src/Grav/Common/Flex/Types/Users/UserObject.php:727

     * @param string $name
     * @return array|object|null
     * @internal
     */
    public function initRelationship(string $name)
    {
        switch ($name) {
            case 'media':
                $list = [];
                foreach ($this->getMedia()->all() as $filename => $object) {
                    $list[] = $this->buildMediaObject(null, $filename, $object);
                }

                return $list;
            case 'avatar':
                return $this->buildMediaObject('avatar', basename($this->getAvatarUrl()), $this->getAvatarImage());
        }

        throw new \InvalidArgumentException(sprintf('%s: Relationship %s does not exist', $this->getFlexType(), $name));
    }

    /**
     * @return bool Return true if relationships were updated.
     */
    protected function updateRelationships(): bool
    {
        $modified = $this->getRelationships()->getModified();
        if ($modified) {
            foreach ($modified as $relationship) {
                $name = $relationship->getName();
                switch ($name) {
                    case 'avatar':
                        \assert($relationship instanceof ToOneRelationshipInterface);
                        $this->updateAvatarRelationship($relationship);
                        break;
                    default:
                        throw new \InvalidArgumentException(sprintf('%s: Relationship %s cannot be modified', $this->getFlexType(), $name), 400);

View on GitHub (pinned to 6040efed04)

Solutions

  1. Request only 'media' or 'avatar' from user flex objects — those are the two names this type implements.
  2. Whitelist the relationship name before calling the API: in_array($name, ['media', 'avatar'], true) and reject others with your own clear error.
  3. If you genuinely need custom relationships on users, subclass UserObject, register the subclass as the directory's data.object class, and extend the switch with your cases.

Example fix

// before
$rel = $user->getRelationship($name); // InvalidArgumentException for anything but media/avatar

// after
$rel = in_array($name, ['media', 'avatar'], true) ? $user->getRelationship($name) : null;
if (null === $rel) {
    // unknown relationship — handle gracefully (404 / ignore)
}
Defensive patterns

Strategy: type-guard

Validate before calling

$allowed = ['media', 'avatar'];
if (!in_array($name, $allowed, true)) {
    // reject early: unknown relationship for user flex objects
}

Type guard

function isKnownUserRelationship(string $name): bool
{
    return \in_array($name, ['media', 'avatar'], true);
}

Try / catch

try {
    $rel = $user->getRelationship($name);
} catch (\InvalidArgumentException $e) {
    // 404/400: relationship not supported by this flex type
}

Prevention

When it happens

Trigger: Calling the relationship getter with anything other than 'media' or 'avatar' — e.g. 'groups' (groups are a plain property on user data, not a relationship), 'Avatar' (wrong case), or a typo like 'medai'; a REST-style endpoint that forwards a client-supplied relationship name straight into this method.

Common situations: Plugins that assume every flex type supports the same relationship names; admin customizations copying relationship code from a different flex type; client code written against a newer/older Grav where the set of relationships differs.

Related errors


AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17). Data as JSON: /api/errors/0e00c54ee997fc3e. Report an issue: GitHub.