mongodb/laravel-mongodb · error · InvalidArgumentException
Cannot have both " " and " " fields.
Error message
Cannot have both "%s" and "%s" fields.
What it means
The grammar rewrites the '->' arrow notation subfield alias into '.' dot notation. If after the rewrite the target dotted key already exists in the same array with a different value, both entries would conflict, so an InvalidArgumentException naming both keys is thrown.
Solutions
- Use one notation consistently: pick 'address.city' (dot) or 'address->city' (arrow), not both
- Remove the duplicate key whose value is wrong before building the payload
- Make both key values identical if the duplication is intentional (the alias is then applied without error)
- Add a lint rule or helper that normalizes '->' to '.' in payload keys
Example fix
// before $data = ['address->city' => 'Lyon', 'address.city' => 'Paris']; Model::create($data); // after $data = ['address.city' => 'Paris']; Model::create($data);
Defensive patterns
Strategy: validation
Validate before calling
foreach ($data as $k => $v) {
if (str_contains($k, '->')) {
$dot = str_replace('->', '.', $k);
if (array_key_exists($dot, $data) && $v !== $data[$dot]) {
throw new InvalidArgumentException("Conflicting keys '$k' and '$dot'");
}
}
} Type guard
function hasArrowDotConflict(array $values): bool {
foreach ($values as $k => $v) {
if (is_string($k) && str_contains($k, '->')) {
$dot = str_replace('->', '.', $k);
if (array_key_exists($dot, $values) && $v !== $values[$dot]) return true;
}
}
return false;
} Try / catch
try {
$model->create($data);
} catch (\InvalidArgumentException $e) {
if (str_contains($e->getMessage(), 'Cannot have both')) {
$data = normalizeArrowKeys($data); // replace '->' with '.'
$model->create($data);
} else { throw $e; }
} Prevention
- Standardize on dot notation for nested fields in your codebase
- Normalize keys with a helper before building attribute arrays
- Lint for mixed '->' and '.' keys in payload construction
When it happens
Trigger: Passing a payload to prepareFieldsForQuery (via insert/create/update attributes) containing e.g. both 'address->city' and 'address.city' keys with different values.
Common situations: Mixing Laravel dot/arrow syntax in nested attribute arrays; copying field definitions from two code styles; template-built payloads where some keys use '->' and others use '.'.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- Cannot have both "id" and "_id" fields.
- This method is not supported by MongoDB
- This method is not supported by MongoDB. Use vectorSearch()…
- This method is not supported by MongoDB. Use vectorSearch()…
- This method is not supported by MongoDB. Use vectorSearch()…
AI-assisted analysis of mongodb/laravel-mongodb@0634653039 (2026-09-15).
Data as JSON: /api/errors/915bc82b06b7b725.
Report an issue: GitHub.
Appendix: source
Thrown at src/Query/Grammar.php:66
if (array_key_exists('id', $values) && ($root || $this->connection->getRenameEmbeddedIdField())) {
if (array_key_exists('_id', $values) && $values['id'] !== $values['_id']) {
throw new InvalidArgumentException('Cannot have both "id" and "_id" fields.');
}
$values['_id'] = $values['id'];
unset($values['id']);
}
foreach ($values as $key => $value) {
if (! is_string($key)) {
continue;
}
// "->" arrow notation for subfields is an alias for "." dot notation
if (str_contains($key, '->')) {
$newKey = str_replace('->', '.', $key);
if (array_key_exists($newKey, $values) && $value !== $values[$newKey]) {
throw new InvalidArgumentException(sprintf('Cannot have both "%s" and "%s" fields.', $key, $newKey));
}
$values[$newKey] = $value;
unset($values[$key]);
$key = $newKey;
}
// ".id" subfield are alias for "._id"
if (str_ends_with($key, '.id') && $this->connection->getRenameEmbeddedIdField()) {
$newKey = substr($key, 0, -3) . '._id';
if (array_key_exists($newKey, $values) && $value !== $values[$newKey]) {
throw new InvalidArgumentException(sprintf('Cannot have both "%s" and "%s" fields.', $key, $newKey));
}
$values[$newKey] = $value;
unset($values[$key]);
}
}View on GitHub (pinned to 0634653039)