Add/remove alias silently resets Display Mode list at next check

Hi McNeel team, after a significant debugging session on some of our internal code, I seem to have find a really specifically odd bug. I have had Claude narrow it down through the MCP-link and have also tested the observations myself and can confirm the unexpected behaviour. Please find Claudes formal report below:**

Rhino version:** 8.32.26160.13001
OS: Windows 11
Script engine: Rhino’s built-in Python 3 (CPython 3.9.10) via the ScriptEditor

Summary

Calling rhinoscriptsyntax.AddAlias() or rhinoscriptsyntax.DeleteAlias(), either one alone, no other change needed, appears to silently reset Rhino.Display.DisplayModeDescription’s list back to some earlier/stale in-memory or on-disk state. A display mode created after that state was captured disappears entirely, without ever being deleted.

The tricky part: this is not visible within the same script execution. GetDisplayModes() continues to report correctly right after the alias call, and even later in the same script. The reset only becomes visible the next time anything queries display modes in a separate execution, the next script run, or opening Options > Display Modes.

I ran into this while debugging why a company-wide “enforce our custom display modes” setup script kept intermittently losing its changes between runs, with no code difference and no user action in between. Once isolated, it reproduces reliably and is not specific to our codebase a two-line, unrelated alias add+remove is seemingly enough to trigger it.

Steps to reproduce

Run these as two separate script executions (e.g. two separate -ScriptEditor Run calls, or paste into the editor and run, close, reopen, run again, not two functions called back to back in one script,the bug will not show up that way).

Step 1:

import Rhino
import rhinoscriptsyntax as rs

PROBE_NAME = "ZZZ_REPRO_PROBE"
ALIAS_NAME = "ZZZ_REPRO_ALIAS"

existing = Rhino.Display.DisplayModeDescription.FindByName(PROBE_NAME)
if existing:
    Rhino.Display.DisplayModeDescription.DeleteDisplayMode(existing.Id)

shaded = Rhino.Display.DisplayModeDescription.FindByName("Shaded")
probe_id = Rhino.Display.DisplayModeDescription.CopyDisplayMode(shaded.Id, PROBE_NAME)
print("Created probe:", probe_id)
print("Present now:", Rhino.Display.DisplayModeDescription.FindByName(PROBE_NAME) is not None)

# the only other thing this script does - nothing here touches display modes
rs.AddAlias(ALIAS_NAME, "_Line")
rs.DeleteAlias(ALIAS_NAME)

print("Present at end of THIS script:", Rhino.Display.DisplayModeDescription.FindByName(PROBE_NAME) is not None)

Output:

Created probe: <guid>
Present now: True
Present at end of THIS script: True

Step 2 (separate run):

import Rhino

PROBE_NAME = "ZZZ_REPRO_PROBE"
present = Rhino.Display.DisplayModeDescription.FindByName(PROBE_NAME) is not None
print("Present in a separate script run:", present)

Expected result

True — the probe mode was never deleted, so it should still be there.

Actual result

False. The probe mode is gone. GetDisplayModes() in this second run also shows several other modes have reverted to an older state (in our case, some display modes we’d deleted in earlier, unrelated sessions were back too), consistent with the whole list being reset to a stale snapshot rather than just our probe specifically disappearing.

Additional notes

  • Reproduced with rs.AddAlias alone, and separately with rs.DeleteAlias alone — either is independently sufficient.
  • Not tied to command-line nesting: wrapping the display-mode-affecting code in its own separate -ScriptEditor Run command invoked from inside the alias-touching script doesn’t help — the reset still eventually surfaces on the next external check.
  • Not a one-off timing fluke tied to Rhino’s idle loop as far as we could tell — we tried explicitly pumping idle via Rhino.RhinoApp.Wait() and subscribing a one-shot Rhino.RhinoApp.Idle handler to redo the display-mode fix after the alias call; the reset still eventually reappeared on a later check regardless.
  • Once no further alias is added/removed, the display mode state is stable indefinitely (verified with repeated checks across separate runs) — so this really does look tied specifically to alias add/remove, not a general periodic resync.

Question

Is this expected behavior (e.g. aliases and display modes sharing some cached “Options” profile object that gets naively reloaded/rewritten on alias changes), or a bug? Is there a way to force a flush/commit of Display Mode changes so they survive a subsequent alias change?

Happy to provide more detail, a screen recording, or test a build, this has cost us a fair amount of debugging time since it looks like flaky/racy script logic when it actually seems to be a Rhino-side state reset.

Hi @jirrivdb,

Does this work any better?

import Rhino

PROBE_NAME = "ZZZ_REPRO_PROBE"
ALIAS_NAME = "ZZZ_REPRO_ALIAS"

existing = Rhino.Display.DisplayModeDescription.FindByName(PROBE_NAME)
if existing:
    Rhino.Display.DisplayModeDescription.DeleteDisplayMode(existing.Id)

shaded = Rhino.Display.DisplayModeDescription.FindByName("Shaded")
probe_id = Rhino.Display.DisplayModeDescription.CopyDisplayMode(shaded.Id, PROBE_NAME)

# force the new mode to disk now, before anything else can trigger a settings reload
probe = Rhino.Display.DisplayModeDescription.GetDisplayMode(probe_id)
Rhino.Display.DisplayModeDescription.UpdateDisplayMode(probe)

print("Created probe:", probe_id)
print("Present now:", Rhino.Display.DisplayModeDescription.FindByName(PROBE_NAME) is not None)

# the only other thing this script does - nothing here touches display modes
Rhino.ApplicationSettings.CommandAliasList.Add(ALIAS_NAME, "_Line")
Rhino.ApplicationSettings.CommandAliasList.Delete(ALIAS_NAME)

print("Present at end of THIS script:", Rhino.Display.DisplayModeDescription.FindByName(PROBE_NAME) is not None)

– Dale

Hi @dale,

Thanks for the quick suggestion. I tested your option as part of a test suite with my initial problem and a control, unfortunately it doesn’t fix the issue.

I ran three variants, each as isolated probe/alias pairs across separate executions:

  1. Your fix: CopyDisplayMode + explicit GetDisplayMode/UpdateDisplayMode to force the write, then alias add/delete via the raw RhinoCommon API (Rhino.ApplicationSettings.CommandAliasList.Add/Delete instead of rs.AddAlias/rs.DeleteAlias).
  2. Original report script: unchanged, using rs.AddAlias/rs.DeleteAlias.
  3. Control: identical probe creation, but no alias call at all in the script.

Results, checked in a subsequent separate script run:

Variant Alias touched Present at end of same run Present in later separate run
Control (no alias) No True True
Your fix Yes True False
Original report Yes True False

The control does confirm that display modes normally persist fine across separate runs in this setup, so the loss in the other two doesn’t seem to be a test artifact. Both alias-touching variants lost the probe identically.

Two things this might narrow down for you:

  • Explicitly calling UpdateDisplayMode() right after creation doesn’t seem to help. It might not be forcing a disk write, or the alias-triggered reload is clobbering the persisted state too, not just an in-memory cache.
  • Swapping rs.AddAlias/rs.DeleteAlias for the raw RhinoCommon Rhino.ApplicationSettings.CommandAliasList.Add/Delete made no difference. So this also doesn’t seem to be a rhinoscriptsyntax wrapper issue as it reproduces with any API surface that touches the alias list, which matches what we’d already found on our end.

Happy to run further variants if that’s useful.

-Jirri

Hi @jirrivdb,

Thanks for getting back to me. I’ve logged an issue so I can look into this further.

– Dale

RH-97159 is fixed in Rhino 8 Service Release 35