{"record":{"id":"effdee49efa594d6","repo":"stride3d/stride","slug":"the-replacement-asset-can-t-be-null-when-fixing-a-reference","errorCode":null,"errorMessage":"The replacement asset can't be null when fixing a reference","messagePattern":"The replacement asset can't be null when fixing a reference","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/editor/Stride.Core.Assets.Editor/Components/FixReferences/ReferenceReplacementViewModel.cs","lineNumber":47,"sourceCode":"\n        public T Referencer { get; }\n\n        public T ReplacementObject { get { return replacementObject; } set { SetValue(ref replacementObject, value, () => fixReferences.UpdateCommands()); } }\n\n        public bool DontFixReference { get { return dontFixReference; } set { SetValue(ref dontFixReference, value, () => fixReferences.UpdateCommands()); } }\n\n        public ICommandBase PickupReplacementObjectCommand { get; }\n\n        public void FixReference()\n        {\n            if (DontFixReference)\n            {\n                ClearReference();\n            }\n            else\n            {\n                if (ReplacementObject == null)\n                    throw new InvalidOperationException(\"The replacement asset can't be null when fixing a reference\");\n\n                ReplaceReference();\n            }\n        }\n\n        public abstract void ClearReference();\n\n        protected abstract void ReplaceReference();\n\n        protected async Task PickupReplacementObject()\n        {\n            var replacement = await fixReferences.PickupObject(ObjectToFix, propertyType);\n            if (replacement != null)\n            {\n                ReplacementObject = replacement;\n            }\n        }\n    }","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/editor/Stride.Core.Assets.Editor/Components/FixReferences/ReferenceReplacementViewModel.cs#L29-L65","documentation":"ReferenceReplacementViewModel.FixReference throws InvalidOperationException (not an argument exception) when a replacement is requested but the ReplacementObject property is still null. The method decides between ClearReference and ReplaceReference based on whether a deletion or replacement is being fixed.","triggerScenarios":"Calling FixReference() on a reference whose replacement mode is active while the user never picked a replacement asset (ReplacementObject == null).","commonSituations":"Clicking 'Fix' in the Fix References dialog without selecting a substitute asset, or programmatic fixing where the replacement was not assigned first.","solutions":["Assign ReplacementObject to a valid asset before calling FixReference()","Force the clear-reference mode instead (ClearReference()) when no replacement is intended","Disable the fix action in the UI until a replacement is selected"],"exampleFix":"// before\nviewModel.FixReference();\n// after\nif (viewModel.ReplacementObject == null)\n    viewModel.ClearReference();\nelse\n    viewModel.FixReference();","handlingStrategy":"validation","validationCode":"if (vm.ReplacementObject == null) { vm.ClearReference(); } else { vm.FixReference(); }","typeGuard":"static bool HasReplacement([NotNullWhen(true)] object? r) => r is not null;","tryCatchPattern":"try { vm.FixReference(); } catch (InvalidOperationException ex) { logger.LogWarning(ex, \"No replacement selected; clearing reference instead\"); vm.ClearReference(); }","preventionTips":["Enable the fix action only after a replacement is chosen","Decide clear-vs-replace explicitly in calling code","Validate ReplacementObject before invoking FixReference programmatically"],"tags":["invalid-state","null-reference","viewmodel"],"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-15T23:17:13.987Z"}