{"record":{"id":"32e3a1b7462b4def","repo":"sschmid/Entitas","slug":"entitylink-is-already-unlinked","errorCode":null,"errorMessage":"EntityLink is already unlinked!","messagePattern":"EntityLink is already unlinked!","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/Entitas.Unity/Entity/EntityLink.cs","lineNumber":25,"sourceCode":"    {\n        public Entity Entity => _entity;\n\n        Entity _entity;\n        bool _applicationIsQuitting;\n\n        public void Link(Entity entity)\n        {\n            if (_entity != null)\n                throw new Exception($\"EntityLink is already linked to {_entity}!\");\n\n            _entity = entity;\n            _entity.Retain(this);\n        }\n\n        public void Unlink()\n        {\n            if (_entity == null)\n                throw new Exception(\"EntityLink is already unlinked!\");\n\n            _entity.Release(this);\n            _entity = null;\n        }\n\n        void OnDestroy()\n        {\n            if (!_applicationIsQuitting && _entity != null)\n                Debug.LogWarning($\"EntityLink got destroyed but is still linked to {_entity}!\\nPlease call gameObject.Unlink() before it is destroyed.\");\n        }\n\n        void OnApplicationQuit() => _applicationIsQuitting = true;\n\n        public override string ToString() => $\"EntityLink({gameObject.name})\";\n    }\n\n    public static class EntityLinkExtension\n    {","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/sschmid/Entitas/blob/37547d1bd280f3f1c1ef7edb44f2a206660fbfb4/src/Entitas.Unity/Entity/EntityLink.cs#L7-L43","documentation":"EntityLink.Unlink throws this when _entity is already null, meaning the link was never established or was already released. Unlink would otherwise call entity.Release(this) with a null target and corrupt retain accounting.","triggerScenarios":"Calling entityLink.Unlink() twice, calling Unlink on a fresh EntityLink that was never Linked, or OnDestroy running after Unlink was already called manually.","commonSituations":"Double teardown during Unity object destruction (manual Unlink in code plus OnDestroy auto-unlink), and pooled object cleanup scripts calling Unlink unconditionally.","solutions":["Only call Unlink when entityLink.entity != null","Remove manual Unlink calls that duplicate the automatic OnDestroy cleanup","Check link state in pooled-object reset code before unlinking"],"exampleFix":"// before\nlink.Unlink(); // throws if already unlinked\n// after\nif (link.entity != null) link.Unlink();","handlingStrategy":"validation","validationCode":"if (link.entity != null) link.Unlink();","typeGuard":"bool IsLinked(EntityLink link) => link.entity != null;","tryCatchPattern":null,"preventionTips":["Don't call Unlink manually when OnDestroy already handles it","Track link state in pooling code","Only Unlink links you Linked yourself"],"tags":["unity","entitas","lifecycle","double-unlink"],"backgroundTag":"invalid-state-transition","analyzedSha":"37547d1bd280f3f1c1ef7edb44f2a206660fbfb4","analyzedAt":"2026-09-14T00:26:23.246Z","contentChangedAt":"2026-09-14T00:26:23.246Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}