{"record":{"id":"13a566e793aa5a3b","repo":"stride3d/stride","slug":"tried-to-modify-the-configuration-after-is-has-been-frozen","errorCode":null,"errorMessage":"Tried to modify the configuration after is has been frozen.","messagePattern":"Tried to modify the configuration after is has been frozen\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Input/Gestures/GestureConfig.cs","lineNumber":78,"sourceCode":"        private int requiredNumberOfFingers;\n\n        /// <summary>\n        /// Indicate that the configuration is frozen and cannot be modified anymore by the user.\n        /// </summary>\n        private bool frozen;\n\n        /// <summary>\n        /// Freeze the configuration so that the user cannot modify it anymore.\n        /// </summary>\n        private void Freeze()\n        {\n            frozen = true;\n        }\n\n        internal void CheckNotFrozen()\n        {\n            if (frozen)\n                throw new InvalidOperationException(\"Tried to modify the configuration after is has been frozen.\");\n        }\n\n        /// <summary>\n        /// Create a recognizer for the current configuration.\n        /// </summary>\n        /// <returns></returns>\n        internal GestureRecognizer CreateRecognizer(float screenRatio)\n        {\n            // freeze the configuration so that the user cannot modify it from outside.\n            Freeze();\n\n            return CreateRecognizerImpl(screenRatio);\n        }\n\n        internal abstract GestureRecognizer CreateRecognizerImpl(float screenRatio);\n    }\n}\n","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Input/Gestures/GestureConfig.cs#L60-L96","documentation":"GestureConfig instances are frozen (via Freeze) once the recognizer is built; after that, CheckNotFrozen guards every setter. Modifying any configuration property after freezing throws InvalidOperationException 'Tried to modify the configuration after is has been frozen.'","triggerScenarios":"Setting RequiredNumberOfFingers, MinimumScaleValue, MinimumTranslationDistance, MinimumRotationAngle, MinimumDragDistance, or AllowedErrorMargins after the config was frozen — typically after CreateRecognizer or after the gesture system activated it.","commonSituations":"Attempting live tuning of gesture thresholds at runtime; reusing and mutating a shared frozen config for a new gesture; accidentally calling Freeze earlier than expected (e.g. on first use).","solutions":["Create a new GestureConfig (copy values) and modify the copy, then build a new recognizer","Perform all configuration changes before CreateRecognizer / before the config is frozen","Track a frozen flag in your own code and skip/batch updates after activation"],"exampleFix":"// before\nfrozenConfig.MinimumDragDistance = 20f; // throws\n// after\nvar newConfig = new GestureConfig(frozenConfig); // or copy fields manually\nnewConfig.MinimumDragDistance = 20f;\nvar recognizer = newConfig.CreateRecognizer();","handlingStrategy":"try-catch","validationCode":"// guard all property updates\nif (!configFrozen) config.MinimumDragDistance = 20f;","typeGuard":null,"tryCatchPattern":"try { config.MinimumDragDistance = 20f; }\ncatch (InvalidOperationException) { var copy = new GestureConfig(config); copy.MinimumDragDistance = 20f; }","preventionTips":["Finish all gesture tuning before CreateRecognizer","Copy-and-rebuild when runtime changes are needed","Treat GestureConfig as immutable after startup; keep live-tunable values in your own settings layer"],"tags":["input","gestures","config","immutability"],"backgroundTag":"invalid-state-transition","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}