EllanJiang/GameFramework · error · GameFrameworkException

UI group is invalid.

Error message

UI group is invalid.

What it means

Thrown by UIManager.CloseUIForm when the form is non-null but its UIGroup property is null, i.e. the form was never added to a UI group (never fully opened) or was already detached. Casting uiForm.UIGroup to UIGroup and finding null means the form is not in a valid managed state.

Solutions

  1. Ensure the form was opened through OpenUIForm/OpenUIFormAsync before closing
  2. Guard against double close by checking the form's own state flag before calling CloseUIForm
  3. Check uiForm.UIGroup != null before closing

Example fix

// before
UI.CloseUIForm(form);
// after
if (form.UIGroup != null)
{
    UI.CloseUIForm(form);
}
Defensive patterns

Strategy: validation

Validate before calling

if (form == null || form.UIGroup == null) { Log.Warning("Form not openable/closeable"); return; }

Type guard

bool IsFormAttached(IUIForm f) => f != null && f.UIGroup != null;

Try / catch

try { UI.CloseUIForm(form, userData); } catch (GameFrameworkException ex) { Log.Warning("Form already detached: {0}", ex.Message); }

Prevention

When it happens

Trigger: Closing an IUIForm that was instantiated manually (not via OpenUIForm) so it never received a group; or closing a form twice where the first close removed it from its group.

Common situations: Double-close on rapid hide/show input; forms created via helper InstantiateUIForm without opening; shutdown-order bugs where forms outlive their groups.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of EllanJiang/GameFramework@d0c010b051 (2026-09-15). Data as JSON: /api/errors/03b69928615cf359. Report an issue: GitHub.

Appendix: source

Thrown at GameFramework/UI/UIManager.cs:822

            CloseUIForm(uiForm, null);
        }

        /// <summary>
        /// 关闭界面。
        /// </summary>
        /// <param name="uiForm">要关闭的界面。</param>
        /// <param name="userData">用户自定义数据。</param>
        public void CloseUIForm(IUIForm uiForm, object userData)
        {
            if (uiForm == null)
            {
                throw new GameFrameworkException("UI form is invalid.");
            }

            UIGroup uiGroup = (UIGroup)uiForm.UIGroup;
            if (uiGroup == null)
            {
                throw new GameFrameworkException("UI group is invalid.");
            }

            uiGroup.RemoveUIForm(uiForm);
            uiForm.OnClose(m_IsShutdown, userData);
            uiGroup.Refresh();

            if (m_CloseUIFormCompleteEventHandler != null)
            {
                CloseUIFormCompleteEventArgs closeUIFormCompleteEventArgs = CloseUIFormCompleteEventArgs.Create(uiForm.SerialId, uiForm.UIFormAssetName, uiGroup, userData);
                m_CloseUIFormCompleteEventHandler(this, closeUIFormCompleteEventArgs);
                ReferencePool.Release(closeUIFormCompleteEventArgs);
            }

            m_RecycleQueue.Enqueue(uiForm);
        }

        /// <summary>
        /// 关闭所有已加载的界面。

View on GitHub (pinned to d0c010b051)