MemberJunction / MemberJunction/MJ
CodeGen migrations can ship a hidden UQ_EntityField_EntityID_Sequence collision when an entity has virtual fields
- Dominant language
- TSQL
- Stars
- 29
- Forks
- 6
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 323
Description
When CodeGen adds a real column to an entity that already carries virtual fields, the new field takes the next `100000 + ordinal` Sequence slot, which may be the slot a virtual field already occupies. On the authoring machine, live CodeGen renumbers the virtual field in place, so the collision is invisible there by construction. But CodeGen only emits INSERTs for new fields, never the UPDATE that moves an existing field's Sequence, so the migration ships the collision and fails `UQ_EntityField_EntityID_Sequence` on every fresh database.
First observed instance: `V202608081200__v6.1.x__Durable_EntityAction_Dispatch.sql` assigning RunMode Sequence 100025 on `MJ: Entity Actions`, colliding with virtual field `ScopeEntity` planted at 100025 by `V202608042200`. Full forensics and the verified one-line fix: https://github.com/MemberJunction/MJ/pull/3644#issuecomment-5228277027
Two candidate hardenings, either or both:
1. CodeGen: when a new real field takes a Sequence occupied by an existing (virtual) field, emit the guarded renumber UPDATE alongside the INSERT.
2. CI: a static check over new migrations that extracts EntityField INSERT (EntityID, Sequence) pairs and verifies them against the pairs already established by prior migrations, failing on a duplicate.
The static check is cheap and catches the class regardless of how the migration was authored.
Diagnosed with the exact failure masked as an FK error, which is its own issue (skyway swallowing precedingErrors), filed separately.
Contributor guide
Research direction
Start with V202608081200__v6.1.x__Durable_EntityAction_Dispatch.sql and the earlier V202608042200 migration, comparing their EntityField EntityID and Sequence pairs. Then inspect the CodeGen migration output and CI checks to determine whether guarded renumbering or duplicate detection is the intended scope. Done means fresh databases no longer hit UQ_EntityField_EntityID_Sequence, and the chosen protection is verified against this collision.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- sql
- Domain
- ci-cd, database
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100