ORM upgrade changes query semantics: symptoms, cause, and the test that catches it
An ORM or driver upgrade changes default query behaviour and returns different rows.
ORM upgrade changes query semantics is documented by 3 accepted public reports from 3 organisations, 2 of them published in the last 5 years.
- Likelihood: low (2 public reports in 5 years)
- Impact: high (3 of 3 reports: data)
Symptoms
User-visible
- A routine renewal email reaches customers of other organisations, with their email addresses visible in the To: field.[3]
- A bulk delete filtered on a field not declared in the schema removes every document in the collection.[2]
- The same bulk delete wipes the collection when the filter field exists on only some discriminator models.[2]
- A queryset that filters an annotation or alias with __in and an iterator silently returns no rows after a framework minor release.[1]
Monitoring-visible
- The generated SQL no longer contains the WHERE predicate that restricts rows to the requested organisation.[3]
- Saving a record that was just fetched raises an IntegrityError saying the primary key already exists.[4]
- A forced update on the same record fails because the ORM reports that the row does not exist.[4]
- Errors appear only for records whose ids fall outside the int range, and only in an environment with such ids.[4]
Root causes
- stage: third-party A framework security release changed scope behaviour so that a where clause defined in a scope overrode the condition imposed by an association, and the query returned another organisation's teams.[3]
- stage: third-party A major ODM version started removing filter properties not declared in the schema by default, so the remaining empty filter matched every document.[2]
- stage: release-process An upgrade with no test comparing the rows each query returns before and after it lets a changed default reach production. by design analysis
Public examples
- [1]Django, 2026-09-01. After the Django 6.1 release, __in lookups on annotations or aliases passed an iterator returned an empty queryset and __range lookups raised ValueError, because a change in 6.1 iterated the right-hand side twice; the fix was committed and backported for 6.1.1. primary #37311 (In/Range lookups on annotations consume iterator rhs)
- [2]Mongoose, 2022-09-03. A user reported that in Mongoose 6, deleteMany with a filter on a field not declared in the schema removed every document in the collection, unlike version 5; maintainers attributed it to the version 6 strictQuery default and said they would change it back in 7.0.0. primary mongoose ver 6 deleteMany() removes ALL documents when search options contains field not from schema
- [3]GitHub, 2013-03-19. After GitHub applied a Rails security release, an ActiveRecord scope began overriding the condition of an association, so a renewal email query returned teams from other organisations and the email went to many more GitHub Enterprise customer addresses than intended. primary Today's Email Incident
Practitioner sources cited for symptoms
- [4]Misty De Meo (The Future Is Now), 2025-05-13. After an upgrade to Django 5, saving existing records with ids beyond the int range raised IntegrityError in a QA environment, because model definitions declared int primary keys while the database used bigint and Django 5 returns an empty queryset for overflowing integer filters. practitioner The database row that did and didn't exist
Test classes that catch it
| Test class | Stage | Limitation | Basis |
|---|---|---|---|
| Integration tests | pre-deploy | An integration test catches the changed rows only if its fixtures hold more than one organisation, a filter field missing from the schema, or ids beyond the int range, and three of the reports show the fault appearing only for those data shapes. | by design analysis |
Risk
- Likelihood: low (2 public reports in 5 years)
- Impact: high (3 of 3 reports: data)
| Accepted public reports | 3 |
|---|---|
| Published in the last 5 years | 2 |
| Impact stated: data | 3 |
Pre-release checklist
- PR-01
- PR-02
- PR-03
- PR-04
- PR-05
- PR-06
- PR-07
First 30 minutes
- FM-01
- FM-02
- FM-03
- FM-04
- FM-05
- FM-06
Download the checklist
What catches this: catalogue entries
Listed because their own documentation or site names integration tests on the verification date. Alphabetical. Not a recommendation.
Tools whose documentation names these test classes
- Hoverfly integration source verified 2026-10-21
- Postman integration source verified 2026-10-21
- Serenity BDD integration source verified 2026-10-21
- Testcontainers integration source verified 2026-10-21
- TestNG integration source verified 2026-10-21
Providers whose site names these test classes
- andagon people GmbH integration source verified 2026-10-21
- Appmatics integration source verified 2026-10-21
- AQA Masters integration source verified 2026-10-21
- Cleverix integration source verified 2026-10-21
- Crestech Software Systems integration source verified 2026-10-21
- DeviQA integration source verified 2026-10-21
- Invensis Technologies integration source verified 2026-10-21
- Outpost QA integration source verified 2026-10-21
- Q-Centric GmbH integration source verified 2026-10-21
- QA Madness integration source verified 2026-10-21
- QA Mentor integration source verified 2026-10-21
- QAwerk integration source verified 2026-10-21
- Quality Island integration source verified 2026-10-21
- Soflab Technology integration source verified 2026-10-21
- SQA - Software Quality Assurance S.A. integration source verified 2026-10-21
- SunTec India integration source verified 2026-10-21
- TestFort integration source verified 2026-10-21
- Testhouse integration source verified 2026-10-21
- Testing IT integration source verified 2026-10-21
- TestMatick integration source verified 2026-10-21
- Testscenario integration source verified 2026-10-21
- Zoonou integration source verified 2026-10-21
Only on this page
ORM upgrade changes query semantics belongs to the data migrations group, yet report [2] and report [3] name a third-party dependency upgrade and no schema change at all. One upgrade was a framework security release that changed how a scope combines with an association condition [3]. The other was a major ODM version whose new strict query default turned a filter into an empty filter [2].
Because the schema stays the same, a migration test has nothing to run against. The fault lives in the query the library builds, which is why one report traced the change to a single framework commit [3].
Related incidents
- Schema drift between services Two services expect different versions of a shared schema after one is deployed without the other.
- Encoding or timezone shift Stored timestamps or strings are shifted or corrupted after a driver, locale or timezone change.
- Soft-delete flag ignored A new code path ignores a soft-delete flag and exposes or modifies deleted records.
- Dependency removed from registry A package or version is pulled from a registry and builds or deploys fail.
- In-app purchase receipt validation fails Store receipts are rejected after a validation or sandbox endpoint change.
Questions
What causes ORM upgrade changes query semantics?
All three primary reports trace it to a third-party upgrade. A framework security release let a scope override an association condition [3], and a major ODM version dropped undeclared filter fields by default [2]. In report [1], a framework release iterated a lookup's input twice, so an __in filter on an annotation returned no rows.
What are the symptoms of ORM upgrade changes query semantics?
Users see emails sent to other organisations' customers or a whole collection deleted. Monitoring shows a generated SQL query without its organisation WHERE predicate [3]. In report [1], an __in filter on an annotation with an iterator silently returned no rows.
Why did tests not catch ORM upgrade changes query semantics?
In reports [2] and [3] and the practitioner report, the fault showed only for specific data shapes: several organisations, a filter field missing from the schema, or ids beyond the int range. One practitioner report found the int range case only in QA, with no errors in the development environment [4].
Which test class catches ORM upgrade changes query semantics, and what does it miss?
Integration tests are listed by design, because ORM semantics is a stated catch of that class. An integration test misses the change if its fixtures hold only one organisation or only schema-declared filter fields.
Which public reports document ORM upgrade changes query semantics?
3 primary reports document it, from 2013 [3], 2022 [2] and 2026 [1]. A 2025 practitioner report is cited for monitoring symptoms only [4].
Should a team roll back or fix forward when ORM upgrade changes query semantics happens?
Checklist item FM-03 pins the ORM back or sets the changed default explicitly, whichever restores the missing condition faster. The ODM maintainers pointed to setting the strict query option to false as the manual fix [2]. In report [1], the framework fixed forward with a commit backported to the next patch release.
Release Incident Playbook (2026). ORM upgrade changes query semantics: symptoms, cause, and the test that catches it, content version 1.0.0. https://releasefailures.com/incidents/orm-upgrade-changes-query-semantics/. Accessed 2026-10-21.