{"record":{"id":"11b8ea625e3e9451","repo":"EllanJiang/GameFramework","slug":"ui-form-is-invalid-uimanager","errorCode":null,"errorMessage":"UI form is invalid.","messagePattern":"UI form is invalid\\.","errorType":"exception","errorClass":"GameFrameworkException","httpStatus":null,"severity":"error","filePath":"GameFramework/UI/UIManager.cs","lineNumber":816,"sourceCode":"        /// <summary>\n        /// 关闭界面。\n        /// </summary>\n        /// <param name=\"uiForm\">要关闭的界面。</param>\n        public void CloseUIForm(IUIForm uiForm)\n        {\n            CloseUIForm(uiForm, null);\n        }\n\n        /// <summary>\n        /// 关闭界面。\n        /// </summary>\n        /// <param name=\"uiForm\">要关闭的界面。</param>\n        /// <param name=\"userData\">用户自定义数据。</param>\n        public void CloseUIForm(IUIForm uiForm, object userData)\n        {\n            if (uiForm == null)\n            {\n                throw new GameFrameworkException(\"UI form is invalid.\");\n            }\n\n            UIGroup uiGroup = (UIGroup)uiForm.UIGroup;\n            if (uiGroup == null)\n            {\n                throw new GameFrameworkException(\"UI group is invalid.\");\n            }\n\n            uiGroup.RemoveUIForm(uiForm);\n            uiForm.OnClose(m_IsShutdown, userData);\n            uiGroup.Refresh();\n\n            if (m_CloseUIFormCompleteEventHandler != null)\n            {\n                CloseUIFormCompleteEventArgs closeUIFormCompleteEventArgs = CloseUIFormCompleteEventArgs.Create(uiForm.SerialId, uiForm.UIFormAssetName, uiGroup, userData);\n                m_CloseUIFormCompleteEventHandler(this, closeUIFormCompleteEventArgs);\n                ReferencePool.Release(closeUIFormCompleteEventArgs);\n            }","sourceCodeStart":798,"sourceCodeEnd":834,"githubUrl":"https://github.com/EllanJiang/GameFramework/blob/d0c010b05167c58e92350449d04864a91ca13fd2/GameFramework/UI/UIManager.cs#L798-L834","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the IUIForm reference for null before calling CloseUIForm","Track form lifetime via the UIComponent's OpenUIFormSuccess/Close events instead of caching raw references","Use CloseUIForm(serialId, userData) with the serialId returned by OpenUIForm so the manager resolves the form itself"],"exampleFix":"// before\nm_BackpackForm.OnHide();\nUI.CloseUIForm(m_BackpackForm);\n// after\nif (m_BackpackForm != null)\n{\n    UI.CloseUIForm(m_BackpackForm);\n    m_BackpackForm = null;\n}","handlingStrategy":"validation","validationCode":"if (form == null) { Log.Warning(\"Skip CloseUIForm: form is null\"); return; }","typeGuard":"bool IsValidForm(IUIForm f) => f != null;","tryCatchPattern":"try { UI.CloseUIForm(form, userData); } catch (GameFrameworkException ex) { Log.Warning(\"CloseUIForm failed: {0}\", ex.Message); }","preventionTips":["Never cache UIForm references before OpenUIFormSuccess fires","Set cached references to null in the form's OnClose","Prefer serialId-based CloseUIForm over object references"],"tags":["unity","gameframework","ui","null-argument"],"backgroundTag":"null-argument","analyzedSha":"d0c010b05167c58e92350449d04864a91ca13fd2","analyzedAt":"2026-09-15T13:37:15.352Z","contentChangedAt":"2026-09-15T13:37:15.352Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}