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
- Fix the page frontmatter so authors is a flat list of quoted username strings: permissions: { authors: [jane, john] }.
- Quote numeric-looking usernames so YAML keeps them strings: authors: ['12345'].
- Normalize data before it reaches the page: in onAdminSave, map author entries to strings (e.g. $author['name'] ?? null).
- 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
- Author frontmatter must be a flat list of quoted usernames (authors: [jane, john]).
- Quote numeric usernames so YAML keeps them strings.
- Normalize on save via onAdminSave hooks in plugins that write author metadata.
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
- Invalid storage key: "%s"
- Invalid argument $value
- Invalid argument $element
- Failed to save file '%s': %s
- Encoding markdown failed
AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17).
Data as JSON: /api/errors/4256630e28d4a4cc.
Report an issue: GitHub.