The error:
Transaction numbers are only allowed on a replica set member or mongos
means that your code is attempting to use MongoDB transactions, but your MongoDB server is running as a standalone instance, not as a replica set or sharded cluster (mongos). Transactions are only supported on replica sets or sharded clusters.
Why is this happening after upgrading to mongodb/laravel-mongodb v5?
Starting with v4 and especially v5, the mongodb/laravel-mongodb package uses transactions by default for certain operations (like save, update, etc.) if your database connection supports them. If your local or CI MongoDB is not a replica set, these operations will fail with the error you’re seeing.
Why does it only happen in one place?
It’s likely that only this particular update operation is using a transaction (possibly due to relationships, events, or the way Nova handles updates).
Solution
1. Run MongoDB as a Replica Set Locally and in CI
The recommended solution is to run MongoDB as a replica set, even if it’s a single-node replica set. This is the setup you’ll have in production (Atlas), and it ensures consistency between environments.
Local (Homebrew) Setup:
Stop your current MongoDB instance and restart it as a replica set:
brew services stop mongodb-community
mongod --replSet rs0 --dbpath /usr/local/var/mongodb
In a new terminal, initiate the replica set:
mongo
> rs.initiate()
Now your local MongoDB supports transactions.
CI (CircleCI) Setup:
Update your CircleCI config to start MongoDB as a replica set. Example for a Docker-based job:
- run:
name: Start MongoDB as a replica set
command: |
mongod --replSet rs0 --fork --logpath /var/log/mongodb.log --dbpath /data/db
sleep 5
mongo --eval 'rs.initiate()'
2. (Alternative) Disable Transactions for Certain Operations
If you cannot use a replica set locally or in CI, you can disable transactions for specific operations by wrapping them in a withoutTransaction closure provided by the package:
use Jenssegers\Mongodb\Eloquent\Model;
Model::withoutTransaction(function () use ($account, $data) {
$account->update($data);
});
Or, if you want to globally disable transactions (not recommended for production):
// In your config/database.php under the mongodb connection:
'options' => [
'transactions' => false,
],
3. Check for Package or Nova Customizations
If you have custom Nova resources or observers that explicitly use transactions, you may need to update them to use withoutTransaction as above.
Summary
- The error is due to transactions being used on a standalone MongoDB.
- The best fix is to run MongoDB as a replica set locally and in CI.
- Alternatively, disable transactions for the affected operation using
Model::withoutTransaction. - No changes are needed for production if you’re using Atlas (which is a replica set).
References:
Let me know if you need a step-by-step for your specific environment!