Skip to content

Any settings write fails with "element id(s) are used more than once" when two server configurations share a name (the second one is written twice) #1837

Open

Description

@jaydenconclusion

1. mxcli version: nightly-20261111-0036eef98 (Windows, amd64); also seen on nightly-20261030-aed6c2092
2. Mendix version: 11.12.5
Repro app: a fresh mxcli new app, built by the script below

3. Scenario

When the project settings hold two server configurations with the same name, every settings write fails with "element id(s) are used more than once". That includes writes that have nothing to do with configurations (alter settings runtime, alter settings language), and therefore mxcli test, which sets its own after-startup microflow. Studio Pro accepts duplicate configuration names (the project opens normally); in our team app the duplicate arrived through a merge. The unit on disk is valid (mx check passes, all ids are unique). The duplicated id is the second configuration's, so mxcli seems to match configurations by name and write the second one twice.

Self-contained repro, run in an empty directory (the Python step adds a second configuration with the same name and fresh element ids):

#!/usr/bin/env bash
# Repro: two server configurations with the same name make every settings write fail with "element id used more than once".
# Needs mxcli, python3 (stdlib only).
set -e
cd "$(dirname "$0")"
export MXCLI_LOG_DIR="$PWD/logs"
P=Repro/Repro.mpr
PY=${PYTHON:-python3}
mxcli new Repro --version 11.12.5 --skip-build > /dev/null

# A second configuration with the same Name and fresh element ids (how it typically arrives via a merge). Done here as a BSON edit.
$PY - Repro <<'PY'
import sys, glob, struct, uuid
f = [p for p in glob.glob(sys.argv[1] + '/mprcontents/**/*.mxunit', recursive=True)
     if b'Settings$ProjectSettings' in open(p, 'rb').read()][0]
b = bytearray(open(f, 'rb').read())
def cstr(i):
    j = b.index(0, i); return b[i:j].decode(), j + 1
def elems(i):
    end = i + struct.unpack_from('<i', b, i)[0]; j = i + 4
    while j < end - 1:
        s = j; t = b[j]; j += 1; k, j = cstr(j); v = j
        if t in (3, 4): j += struct.unpack_from('<i', b, j)[0]
        elif t == 2: j += 4 + struct.unpack_from('<i', b, j)[0]
        elif t == 5: j += 5 + struct.unpack_from('<i', b, j)[0]
        elif t == 8: j += 1
        elif t == 16: j += 4
        elif t in (1, 9, 17, 18): j += 8
        elif t != 10: raise Exception(t)
        yield k, t, s, v, j
def find(i, key):
    return next(x for x in elems(i) if x[0] == key)
_, _, _, settings, _ = find(0, 'Settings')
cfg_doc = next(v for k, t, s, v, e in elems(settings)
               if t == 3 and any(x[0] == 'Configurations' for x in elems(v)))
_, _, _, cfgs, _ = find(cfg_doc, 'Configurations')
items = [x for x in elems(cfgs) if x[1] == 3]
last = items[-1]
copy = bytearray(b[last[2]:last[4]])
newkey = str(int(last[0]) + 1).encode()
copy = bytes([3]) + newkey + b'\x00' + copy[1 + len(last[0]) + 1:]
copy = bytearray(copy)
marker = b'\x05$ID\x00\x10\x00\x00\x00'
i = copy.find(marker)
n = 0
while i >= 0:
    o = i + len(marker) + 1
    copy[o:o + 16] = uuid.uuid4().bytes_le; n += 1
    i = copy.find(marker, o)
ins = cfgs + struct.unpack_from('<i', b, cfgs)[0] - 1  # before the array's trailing 0x00
b[ins:ins] = copy
for off in (cfgs, cfg_doc, settings, 0):
    struct.pack_into('<i', b, off, struct.unpack_from('<i', b, off)[0] + len(copy))
open(f, 'wb').write(bytes(b))
print('duplicated configuration with', n, 'fresh element ids')
PY
mxcli fix hashes -p $P --repair | tail -1
mxcli -p $P -c "show settings" | grep "Configuration '"

cat > step1.mdl <<'MDL'
mdl 1;
alter settings runtime (HashAlgorithm: 'BCrypt');
MDL
mxcli -p $P exec step1.mdl || true
mxcli docker check -p $P | tail -1 || true

Output (progress lines left out):

duplicated configuration with 1 fresh element ids
Repaired 1 ContentsHash value(s) from the files on disk.
| Configuration 'Default' | Hsqldb, db=default, http=8080, url=http://localhost:8080/                    |
| Configuration 'Default' | Hsqldb, db=default, http=8080, url=http://localhost:8080/                    |
Connected to: Repro/Repro.mpr (Mendix 11.12.5)
Error: failed to update project settings: refusing to write unit 4e70063d-53e1-477a-ab92-6b763330c293: 1 element id(s) are used more than once, which produces a project that cannot be opened (Studio Pro reports "Duplicate Guid in unit ..." and refuses the whole project)
  563bb0f4-28e9-4ab0-9d51-e5b89a027603 held by [Settings$ServerConfiguration Settings$ServerConfiguration]
Project check passed.

4. Expected output

  • Settings writes keep both configurations as they are (each with its own ids), and the change is applied.
  • If configurations really have to be addressed by name: only alter settings configuration '<name>' / create configuration / drop configuration should refuse, with a clear message such as "configuration name 'Default' is not unique", and unrelated writes (runtime, language, mxcli test) should still work.

5. Experienced output

The unit on disk before the write (ids read from the BSON):

Configuration $ID on disk In the refusal message
1st Default b6fc893f-… not mentioned
2nd Default (copy) 563bb0f4-… held by two Settings$ServerConfiguration

This suggests the second configuration is written in place of the first. The safety check catches it and nothing is written, but every settings write is blocked until one of the configurations is removed or renamed.

Other spellings tried (same project, same error each time)

  • alter settings configuration 'Default' (HttpPortNumber: 8081); → refusing to write unit …: 1 element id(s) are used more than once … 563bb0f4-… held by [Settings$ServerConfiguration Settings$ServerConfiguration]
  • create configuration 'Other'; → same error
  • alter settings language (DefaultLanguageCode: 'en_US'); → same error
  • mxcli test → fails while preparing: ALTER SETTINGS RUNTIME (AfterStartupMicroflow: 'MxTest.RegisterEndpoint'): … refusing to write unit …

6. AI bug report

mxcli diag of the repro run:

  Version:     nightly-20261111-0036eef98
  Go:          go1.27.3 windows/amd64
  Sessions:    8 (last 7 days)
  Errors:      4 (last 7 days)

Session log of -p Repro/Repro.mpr exec step1.mdl (from mxcli diag --bundle):

{"time":"2026-11-12T14:08:19.4995256+01:00","level":"INFO","msg":"session_start","version":"nightly-20261111-0036eef98","go":"go1.27.3","os":"windows","arch":"amd64","mode":"mxcli exec","args":["mxcli","-p","Repro/Repro.mpr","exec","step1.mdl"],"pid":29000,"parent_pid":""}
{"time":"2026-11-12T14:08:19.7584014+01:00","level":"ERROR","msg":"execute_error","stmt_type":"AlterSettingsStmt","stmt_summary":"alter settings model","error":"failed to update project settings: refusing to write unit 4e70063d-53e1-477a-ab92-6b763330c293: 1 element id(s) are used more than once, which produces a project that cannot be opened (Studio Pro reports \"Duplicate Guid in unit ...\" and refuses the whole project)\n  563bb0f4-28e9-4ab0-9d51-e5b89a027603 held by [Settings$ServerConfiguration Settings$ServerConfiguration]","duration_ms":4}

The log shows a single AlterSettingsStmt that fails on the write itself: the duplicate id appears only in the unit mxcli tries to write.

Why it matters

In a team app every developer keeps their own configuration, and copies with the same name slip in easily (here through a merge). Merges then carry the duplicate name into every branch. From that point on mxcli test and all settings writes fail. Workaround: remove or rename one of the duplicate configurations in Studio Pro.

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

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions