getgrav/grav · error · InvalidArgumentException

500

500

Error message

Iterable should return username (string).

What it means

PageAuthorsTrait::loadAuthors() iterates the 'header.permissions.authors' frontmatter value and requires every yielded element to be a username string; any non-string (nested array, map, number) throws InvalidArgumentException with code 500. The authors list must be a flat list of username strings; anything else is considered malformed page metadata.

Source

Thrown at system/src/Grav/Framework/Flex/Pages/Traits/PageAuthorsTrait.php:104

        return $this->_permissionsCache;
    }

    /**
     * @param iterable $authors
     * @return array<int,UserInterface>
     */
    protected function loadAuthors(iterable $authors): array
    {
        $accounts = $this->loadAccounts();
        if (null === $accounts || empty($authors)) {
            return [];
        }

        $list = [];
        foreach ($authors as $username) {
            if (!is_string($username)) {
                throw new InvalidArgumentException('Iterable should return username (string).', 500);
            }
            $list[] = $accounts->load($username);
        }

        return $list;
    }

    /**
     * @param string $action
     * @param string|null $scope
     * @param UserInterface|null $user
     * @param bool $isAuthor
     * @return bool|null
     */
    public function isParentAuthorized(string $action, ?string $scope = null, ?UserInterface $user = null, bool $isAuthor = false): ?bool
    {
        $scope ??= $this->getAuthorizeScope();

View on GitHub (pinned to 6040efed04)

Solutions

  1. Fix the page frontmatter so authors is a flat list of quoted username strings: permissions: { authors: [jane, john] }.
  2. Quote numeric-looking usernames so YAML keeps them strings: authors: ['12345'].
  3. Normalize data before it reaches the page: in onAdminSave, map author entries to strings (e.g. $author['name'] ?? null).
  4. Catch InvalidArgumentException when rendering author-dependent fields to show a clearer admin message naming the page.

Example fix

# before (page frontmatter)
permissions:
  authors:
    - { name: jane, role: owner }

# after
permissions:
  authors: [jane]
Defensive patterns

Strategy: validation

Validate before calling

// Normalize authors to a flat list of username strings before use/save
$authors = (array) $page->getNestedProperty('header.permissions.authors', []);
$valid = array_filter($authors, 'is_string');
if (count($valid) !== count($authors)) {
    // reject or repair (e.g. extract 'name' keys) before the page is used
    $authors = array_map(
        fn($a) => is_string($a) ? $a : ($a['name'] ?? null),
        $authors
    );
    $page->setNestedProperty('header.permissions.authors', array_filter($authors));
}

Type guard

function isUsernameList(mixed $authors): bool
{
    if (!is_iterable($authors)) { return false; }
    foreach ($authors as $username) {
        if (!is_string($username)) { return false; }
    }
    return true;
}

Prevention

When it happens

Trigger: Frontmatter like permissions: {authors: [{name: jane}]} (list of maps) or authors: {jane: owner} where a value is an array; numeric usernames stored as YAML integers (authors: [123]); JSON-style nested objects under header.permissions.authors.

Common situations: Content authors writing structured author metadata instead of plain usernames; migrating legacy page metadata into permissions.authors without normalizing; plugins writing nested author objects into page headers.

Related errors


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