mongodb/laravel-mongodb · error · InvalidArgumentException
Columns cannot be specified to create an aggregation…
Error message
Columns cannot be specified to create an aggregation builder. Add a $project stage instead.
What it means
When creating a fluent AggregationBuilder via ->aggregate() with no function, column selection is meaningless because projections must be expressed as a $project stage. Passing any columns other than ['*'] raises this InvalidArgumentException.
Solutions
- Call ->aggregate(null) (columns default to ['*']) and add a ->project(...) stage on the AggregationBuilder instead.
- If you want aggregation over specific columns, pass a function: ->aggregate('avg', ['price']).
Example fix
// before
$agg = Model::aggregate(null, ['price']);
// after
$agg = Model::aggregate(null)->project('price'); Defensive patterns
Strategy: validation
Validate before calling
if ($function === null && $columns !== ['*']) {
$columns = ['*']; // or move columns into a $project stage
}
$agg = $model->aggregate($function, $columns); Try / catch
try {
$agg = Model::aggregate(null, $columns);
} catch (InvalidArgumentException $e) {
if (str_contains($e->getMessage(), 'Columns cannot be specified')) {
$agg = Model::aggregate(null)->project($columns);
} else { throw $e; }
} Prevention
- Call aggregate(null) without columns and use ->project() on the builder
- Only pass columns when a function like 'avg' is supplied
- Add static analysis/tests asserting builder-style calls use ['*']
- Document the difference between aggregate(fn, cols) and the fluent builder in your codebase
When it happens
Trigger: Calling ->aggregate('avg', ['price']) — no wait, the builder path only triggers with $function === null; specifically ->aggregate(null, ['price']) or ->aggregate(null, 'price') cast to array.
Common situations: Developers mixing the fluent-builder call style (no function) with the aggregate-with-columns style, expecting column selection to carry over.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Aggregation builder does not support previous query-builder…
- Aggregating by group requires zero or one columns.
- The stage name " " is invalid. It must start with a "$"…
- Query not compatible with cursor
- Aggregation builder requires package mongodb/builder 0.2+
AI-assisted analysis of mongodb/laravel-mongodb@0634653039 (2026-09-15).
Data as JSON: /api/errors/86eb2c8d00baed3a.
Report an issue: GitHub.
Appendix: source
Thrown at src/Query/Builder.php:582
];
return md5(serialize(array_values($key)));
}
/** @return ($function is null ? AggregationBuilder : mixed) */
#[Override]
public function aggregate($function = null, $columns = ['*'])
{
assert(is_array($columns), new TypeError(sprintf('Argument #2 ($columns) must be of type array, %s given', get_debug_type($columns))));
if ($function === null) {
if (! trait_exists(FluentFactoryTrait::class)) {
// This error will be unreachable when the mongodb/builder package will be merged into mongodb/mongodb
throw new BadMethodCallException('Aggregation builder requires package mongodb/builder 0.2+');
}
if ($columns !== ['*']) {
throw new InvalidArgumentException('Columns cannot be specified to create an aggregation builder. Add a $project stage instead.');
}
if ($this->wheres) {
throw new BadMethodCallException('Aggregation builder does not support previous query-builder instructions. Use a $match stage instead.');
}
return new AggregationBuilder($this->collection, $this->options);
}
$this->aggregate = [
'function' => $function,
'columns' => $columns,
];
$previousColumns = $this->columns;
// We will also back up the select bindings since the select clause will be
// removed when performing the aggregate function. Once the query is runView on GitHub (pinned to 0634653039)