{"record":{"id":"0a97765b19a8a830","repo":"mongodb/laravel-mongodb","slug":"the-aggregate-column-name-must-be-a-string","errorCode":null,"errorMessage":"The aggregate column name must be a string.","messagePattern":"The aggregate column name must be a string\\.","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Helpers/QueriesRelationshipAggregates.php","lineNumber":70,"sourceCode":"    private array $withAggregates = [];\n\n    /** @inheritdoc */\n    public function withAggregate($relations, $column, $function = null)\n    {\n        if (empty($relations)) {\n            return $this;\n        }\n\n        if (! in_array($function, self::AGGREGATE_FUNCTIONS, true)) {\n            throw new InvalidArgumentException(sprintf(\n                'Aggregate function \"%s\" is not supported by MongoDB. Supported functions are: %s.',\n                $function ?? 'null',\n                implode(', ', self::AGGREGATE_FUNCTIONS),\n            ));\n        }\n\n        if (! is_string($column)) {\n            throw new InvalidArgumentException('The aggregate column name must be a string.');\n        }\n\n        if (str_starts_with($column, '$')) {\n            throw new InvalidArgumentException(sprintf(\n                'The aggregate column name \"%s\" must not start with \"$\".',\n                $column,\n            ));\n        }\n\n        foreach ($this->parseWithRelations(is_array($relations) ? $relations : [$relations]) as $name => $constraints) {\n            [$name, $alias] = $this->resolveAggregateAlias($name, $function, $column);\n\n            $relation = $this->getRelationWithoutConstraints($name);\n            $this->assertAggregateRelationSupported($relation, $name);\n            $this->assertEmbeddedConstraintsSupported($relation, $name, $constraints);\n\n            // The key used to match the aggregated values with the parent documents must be read.\n            $parentKey = $this->getAggregateParentKey($relation);","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/mongodb/laravel-mongodb/blob/0634653039468ceb0268a69192bdac64469ed043/src/Helpers/QueriesRelationshipAggregates.php#L52-L88","documentation":"withAggregate() requires the aggregate column to be a string (the field being aggregated). Non-string values (arrays, ints, nulls) throw InvalidArgumentException because MongoDB aggregation field names must be strings.","triggerScenarios":"Calling $query->withAggregate('relation', 'sum', 42) or passing an array of columns / null / an object as the column argument.","commonSituations":"Copying SQL usage where multiple columns could be passed; dynamic column built from config that resolves to null; misunderstanding the signature and passing an array of columns.","solutions":["Pass a single string column name, e.g. 'total'","If aggregating multiple columns, call withAggregate once per column","Cast/validate dynamic column values with is_string() before calling","Don't pass null — ensure the config/env default produces a string"],"exampleFix":"// before\n$query->withAggregate('orders', 'sum', ['total', 'tax']);\n// after\n$query->withAggregate('orders', 'sum', 'total');\n$query->withAggregate('orders', 'sum', 'tax');","handlingStrategy":"type-guard","validationCode":"if (!is_string($column)) {\n    throw new InvalidArgumentException('Column must be a string');\n}","typeGuard":"function isStringColumn(mixed $column): bool {\n    return is_string($column) && $column !== '';\n}","tryCatchPattern":"try {\n    $query->withAggregate('orders', 'sum', $column);\n} catch (InvalidArgumentException $e) {\n    if (str_contains($e->getMessage(), 'must be a string')) {\n        Log::error('withAggregate column must be a string', ['column' => $column]);\n    } else {\n        throw $e;\n    }\n}","preventionTips":["Validate that config/env-driven column values are strings with defaults","Call withAggregate once per column rather than passing arrays","Type-hint internal helper functions that feed column names as string"],"tags":["eloquent","aggregates","argument-type"],"backgroundTag":"type-mismatch","analyzedSha":"0634653039468ceb0268a69192bdac64469ed043","analyzedAt":"2026-09-15T02:56:37.067Z","contentChangedAt":"2026-09-15T02:56:37.067Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}