Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →If you use Polyfactory’s SQLAlchemyFactory and your tests fail intermittently with IntegrityError: UNIQUE constraint failed: users.id once you generate a few dozen rows, add one line to the factory: __set_primary_key__ = False. That stops the factory from inventing random primary keys, so the database assigns them and the collisions stop.
This fix is conditional. It fits when the project uses Polyfactory and the traceback names a primary-key column. The sections below cover how to check that, why the failure shows up at random, and what to do if your setup differs.
As an Amazon Associate I earn from qualifying purchases.
The fix
from polyfactory.factories.sqlalchemy_factory import SQLAlchemyFactory
class UserFactory(SQLAlchemyFactory[User]):
__set_primary_key__ = False
Polyfactory’s API reference documents __set_primary_key__ as the flag that controls whether primary-key columns are treated as factory fields. The default is True, so by default the factory generates a value for the key itself. Setting it to False leaves the column unset, and the database or ORM supplies the value when the row is persisted. Apply it to every factory whose model has a generated primary key, or to a shared base factory that your other factories inherit from.
Confirm this is your problem first
“Fails at random past 50 rows” does not identify the cause by itself. Check these before changing anything:
#1 Best Overall
- The library.
__set_primary_key__exists only in Polyfactory. If your factories subclassfactory.alchemy.SQLAlchemyModelFactory, you use factory_boy, and the factory_boy section below applies instead. - The exception. It should be an
IntegrityErroron a uniqueness or primary-key constraint, naming the table and the id column. The wording varies by database. SQLite saysUNIQUE constraint failed: users.id, while PostgreSQL reports a duplicate key value violating a unique constraint. - The constrained column. If the failing column is an email, username or slug rather than the primary key, this setting will not help. Those columns need their own unique-value strategy.
- Manual keys. If your tests assign IDs by hand or load fixtures with fixed IDs, the collision may come from your own data and not from the factory.
Why it fails randomly, and only at larger sizes
A Dev Community article with this exact symptom reports that, with Polyfactory 3.3.0 and SQLAlchemy 2.1.1, integer primary keys were filled in using Faker’s pyint(), which the author gives as a range of 0 to 9999. Random draws from a finite range follow the birthday-problem pattern. With only a few rows a collision is unlikely, but each extra row makes one more likely, so the failure seems to appear suddenly and unpredictably as the batch grows. Nothing is wrong with any single row.
As a rough check, a simple birthday estimate for one table drawing from 10,000 values gives about 11% odds of a collision at 50 rows and about 39% at 100. That is arithmetic, not a measurement. The author’s own numbers are higher, which may mean their setup drew more keys than a single table would, for example related rows across several factories.
What the author measured
The article’s author ran 100 repeated attempts per size on fresh SQLite databases and reported these failure counts:
| Rows generated | Failures per 100 runs (author-reported) |
|---|---|
| 50 posts | 25 to 36 |
| 100 posts | 76 to 82 |
| 200 posts | 100 |
| 200 posts with primary-key generation disabled | 0 |
These figures come from one author’s environment and have not been independently reproduced. Treat them as an illustration of the pattern, not a universal threshold. The point where your tests start failing depends on your range, your model and how many related rows you create.
What changes after the fix
With primary-key generation off, the ID is no longer decided in Python. The model’s key column must be one the database can generate, such as an integer primary key with autoincrement behavior. SQLAlchemy usually treats a single integer primary key that way by default, but confirm it for your schema.
One consequence matters for test code. An object created with build() that has not been persisted may still have id = None, because the value only exists after the insert. If a test reads user.id, flush or commit first:
Rank #4
user = UserFactory.build()
session.add(user)
session.flush() # sends the INSERT; user.id is now populated
assert user.id is not None
Polyfactory’s persistence guide shows factory results being persisted with a non-null ID. SQLAlchemy flushes pending changes automatically before a commit, and you can call Session.flush() yourself when you need the ID earlier, without committing.
Related rows and foreign keys
If a child factory needs a parent’s ID, give it the parent object or flush the parent first, so the foreign key is not populated from a still-empty None ID.
Best Value
Recovering a session after a failed flush
Once an IntegrityError has been raised during a flush, SQLAlchemy requires you to call Session.rollback() before using that session again. If a test fixture reuses a session after a collision, later tests can fail with confusing secondary errors. Fix the primary-key collision first, then make sure fixtures roll back or recreate the session between tests.
If you use factory_boy instead
The __set_primary_key__ flag does not exist in factory_boy. Its SQLAlchemy factory controls persistence with sqlalchemy_session_persistence, which accepts None, "flush" or "commit". For values that must be unique, its recipes recommend declaring a factory.Sequence, which produces ever-increasing values and therefore avoids random collisions.
Quick Recap
| Polyfactory | factory_boy | |
|---|---|---|
| Relevant setting | __set_primary_key__ = False |
factory.Sequence for unique values; sqlalchemy_session_persistence for persistence |
| Who creates the primary key | The database, once the flag is off | You choose: the database, or a sequence you declare |
| When the ID is available | After flush or commit | Depends on the persistence mode, or immediately if a sequence assigns it |
Checklist
- Read the traceback and confirm it is a primary-key or unique violation on the table you expect.
- Confirm the factory subclasses Polyfactory’s
SQLAlchemyFactory. - Add
__set_primary_key__ = Falseto the factory or a shared base class. - Check that the model’s key column is database-generated.
- Flush or commit before reading IDs, and roll back sessions between tests.
- Run the large-batch test several times. A random bug needs repeated runs, not one passing run, to be convincing.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minute




