laravel/framework · error · InvalidArgumentException
Invalid aggregate [{$aggregate}] used within ofMany relation
Error message
Invalid aggregate [{$aggregate}] used within ofMany relation. Available aggregates: MIN, MAX What it means
ofMany() on a has-one/has-many relation selects a single representative row by an aggregate (MIN/MAX). The implementation only supports 'min' and 'max' because it builds a deterministic sub-query join; any other aggregate (SUM, AVG, COUNT) is rejected with InvalidArgumentException listing the allowed set.
Source
Thrown at src/Illuminate/Database/Eloquent/Relations/Concerns/CanBeOneOfMany.php:95
$keyName = $this->query->getModel()->getKeyName();
$columns = is_string($columns = $column) ? [
$column => $aggregate,
$keyName => $aggregate,
] : $column;
if (! array_key_exists($keyName, $columns)) {
$columns[$keyName] = 'MAX';
}
if ($aggregate instanceof Closure) {
$closure = $aggregate;
}
foreach ($columns as $column => $aggregate) {
if (! in_array(strtolower($aggregate), ['min', 'max'])) {
throw new InvalidArgumentException("Invalid aggregate [{$aggregate}] used within ofMany relation. Available aggregates: MIN, MAX");
}
$subQuery = $this->newOneOfManySubQuery(
$this->getOneOfManySubQuerySelectColumns(),
array_merge([$column], $previous['columns'] ?? []),
$aggregate,
);
if (isset($previous)) {
$this->addOneOfManyJoinSubQuery(
$subQuery,
$previous['subQuery'],
$previous['columns'],
);
}
if (isset($closure)) {
$closure($subQuery);View on GitHub (pinned to bd6b5437e6)
Solutions
- Use only 'MIN' or 'MAX' for ofMany (e.g. ->ofMany('price', 'MAX') for the most expensive).
- For more complex selection, pass a closure to ofMany() and build the sub-query manually.
- If you need an average/sum-based representative, compute it separately and select the matching row with a custom where/subquery.
Example fix
// before
return $this->hasOne(Order::class)->ofMany('total', 'AVG');
// after
return $this->hasOne(Order::class)->ofMany('total', 'MAX'); Defensive patterns
Strategy: type-guard
Validate before calling
$aggregate = strtoupper($aggregate);
if (! in_array($aggregate, ['MIN', 'MAX'], true)) {
throw new \InvalidArgumentException("ofMany supports only MIN/MAX, got {$aggregate}");
}
$relation->ofMany($column, $aggregate); Type guard
function isValidOfManyAggregate(string $aggregate): bool {
return in_array(strtoupper($aggregate), ['MIN', 'MAX'], true);
} Prevention
- Restrict ofMany aggregates to MIN/MAX.
- Use a closure for complex ofMany selection logic.
- Compute AVG/SUM representatives separately and select the matching row.
When it happens
Trigger: Calling ->ofMany('price', 'AVG') or ->ofMany('score', 'sum'), or passing an array of column=>aggregate with a non-min/max value.
Common situations: Wanting an 'average' or 'total' representative row (which ofMany cannot express); copy-paste from SQL with a SUM/AVG; typos or wrong-case aggregates (case is lowercased before check, so case isn't the issue).
Related errors
- Collection given to whereBelongsTo method may not be empty.
- Collection given to whereAttachedTo method may not be empty.
- Call to undefined method %s::%s()
- The provided value may not be null.
- Model attribute value is an object but does not have a __toS
AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06).
Data as JSON: /data/errors/ecf27c1f4ef993f8.json.
Report an issue: GitHub.