Skip to content

Any MDL write to an existing entity regenerates attribute storage GUIDs → Mendix DB sync drops and recreates every column (data loss) #1119

Description

Summary

Every mxcli command that re-serialises an existing persistent entity resets each attribute's second (storage/runtime) GUID to the element $ID. The Mendix runtime's database synchroniser identifies columns by that storage GUID (mendixsystem$attribute.id), so on the next deploy it treats every attribute as "deleted + new attribute added": it drops the old columns and creates empty ones. All attribute values are lost; rows and associations survive.

No warning is emitted by mxcli, mx check, or the deployment pipeline. The problem only becomes visible when the package is deployed to a database that already contains data.

Impact

Production deploy on 2026-09-11 wiped every attribute (Name, URLName, Status, … 28 attributes) of all 607 rows of a Masterdata.Organization entity after a single MDL edit of that entity. Recovery required a DB restore plus a byte-level patch of the .mxunit to restore the original GUIDs.

Environment

  • mxcli nightly build of 2026-09-08 (Windows, amd64)
  • Mendix 10.x project (MPR v2, mprcontents/**/*.mxunit)
  • PostgreSQL database with existing data

Steps to reproduce

  1. Take a project with a persistent entity that already has data in a deployed database.
  2. Export the attribute storage IDs from the deployed DB and note the id values for the entity's attributes:
    pg_restore -t 'mendixsystem$attribute' -f meta.sql <backup>
    
  3. Run any of the following against the entity (each one was tested separately on a fresh copy of the project):
    • CREATE OR MODIFY ENTITY Module.Entity (...)
    • ALTER ENTITY Module.Entity ADD ATTRIBUTE ...
    • ALTER ENTITY Module.Entity MODIFY ATTRIBUTE ...
    • ALTER ENTITY Module.Entity RENAME ATTRIBUTE ...
    • ALTER ENTITY Module.Entity DROP ATTRIBUTE ...
    • ALTER ENTITY Module.Entity SET DOCUMENTATION '...'
  4. Inspect the entity's .mxunit (BSON) again: every attribute now has its storage GUID equal to its $ID. In our case 0 of 28 original storage GUIDs survived, for every command above — including SET DOCUMENTATION, which touches no attribute at all.
  5. Build and deploy to the database from step 1. The runtime logs the attributes as removed/added and drops + recreates the columns.

Commands that did not touch the existing GUIDs (27/28 kept — only the newly added items differ):

  • CREATE PERSISTENT ENTITY ... (new entity)
  • CREATE ASSOCIATION ... pointing at the existing entity

Expected behaviour

Re-serialising an entity must preserve the storage GUID of every attribute that was not explicitly dropped. Only newly created attributes should get a fresh GUID. Ideally the CLI should also refuse (or at least warn loudly) when a write would change the storage GUID of an existing attribute.

Actual behaviour

Storage GUID is overwritten with $ID on every write, silently.

Technical notes

Each attribute in the unit carries two GUIDs: the element $ID and a second GUID that the runtime uses as mendixsystem$attribute.id. In a Studio Pro–authored unit these differ; after an mxcli write they are identical. We recovered by byte-patching the 28 original GUIDs back into the unit (.NET GUID byte order) and recomputing the unit's ContentsHash = base64(sha256(unit bytes)) in the .mpr Unit table, then deploying — data was intact afterwards, confirming the GUID is the only thing the synchroniser keys on.

Happy to provide a minimal .mpr + before/after unit dumps if useful.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions