EllanJiang/GameFramework · error · GameFrameworkException

UI form is invalid.

Error message

UI form is invalid.

What it means

GameFramework's UIManager.CloseUIForm throws this when the IUIForm argument passed in is null. Closing a form requires dereferencing its UIGroup and calling lifecycle methods, so a null form is rejected immediately. It is a guard against programming mistakes, not a runtime condition.

Solutions

  1. Check the IUIForm reference for null before calling CloseUIForm
  2. Track form lifetime via the UIComponent's OpenUIFormSuccess/Close events instead of caching raw references
  3. Use CloseUIForm(serialId, userData) with the serialId returned by OpenUIForm so the manager resolves the form itself

Example fix

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

Strategy: validation

Validate before calling

if (form == null) { Log.Warning("Skip CloseUIForm: form is null"); return; }

Type guard

bool IsValidForm(IUIForm f) => f != null;

Try / catch

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

Prevention

When it happens

Trigger: Calling CloseUIForm(IUIForm, object) with a null first argument, e.g. a cached form reference that was never assigned, or CloseUIForm(serialId) path resolving to no open form and forwarding null.

Common situations: Developers cache a UIForm reference before OpenUIForm's async load completes; the open fails and the field stays null; later code closes it unconditionally. Also happens after a form was closed and the cached reference cleared.

Related errors


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

Appendix: source

Thrown at GameFramework/UI/UIManager.cs:816

        /// <summary>
        /// 关闭界面。
        /// </summary>
        /// <param name="uiForm">要关闭的界面。</param>
        public void CloseUIForm(IUIForm uiForm)
        {
            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);
            }

View on GitHub (pinned to d0c010b051)