Repository navigation
LT-22848: Stop Delete Example from crashing the New UI detail view - #1193
Merged
Merged
Conversation
Deleting an Example from its row menu in the Avalonia detail view crashed FieldWorks. That menu runs on the hidden WinForms DataTree, whose rebuild after the delete is postponed, so the deleted object's slice was still listed when the next slice to focus was chosen. The hidden tree was never shown, so focusing that slice built its view, which looked the deleted object up and threw. SelectFirstPossibleSlice now skips a slice whose object has been deleted. A DataTreeTests case reproduces the crash on a tree that is never shown and passes with the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1193 +/- ##
=======================================
Coverage 39.74% 39.74%
=======================================
Files 1544 1544
Lines 355085 355089 +4
Branches 41247 41248 +1
=======================================
+ Hits 141121 141147 +26
+ Misses 184600 184581 -19
+ Partials 29364 29361 -3
🚀 New features to boost your workflow:
|
thejambi
marked this pull request as ready for review
October 20, 2026 16:52
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Start here:
Src/Common/Controls/DetailControls/DataTree.cs,SelectFirstPossibleSlice-- the one changed method.Fixes LT-22848: in the New UI, deleting an Example from its row menu crashed FLEx with "Unable to find hvo ... in the object dictionary". After this change the Example is deleted and the detail view carries on.
Why a WinForms fix cures an Avalonia crash. The Example's row menu is not wholly answered natively, so all of its commands, Delete included, run on the hidden legacy
DataTreethe Avalonia view keeps for command routing.Slice.HandleDeleteCommanddeletes the object, then callsSelectFirstPossibleSlicewith the nearby slices, its own first. The delete postpones the tree's rebuild (the LT-21980 / LT-22011 guard), so that slice still exists. In the visible legacy view its window already exists, so focusing it is harmless and the rebuild discards it. The hidden tree was never shown, so focusing it creates the window, andStringSliceView.MakeRootlooks the deleted object up and throws. The fix skips a slice whose object has been deleted.Where to look
IsDisposedis tested beforeSlice.Object, which throws on a disposed slice.Not here
Verification
DetailControlsTests: 125 passed, 1 skipped (NestedCollapsedPart, skipped onmaintoo). The new test crashes the test host without the fix, with the same exception as the field report.xWorksTestssuite on this branch -- CI runs it.Next: review the one condition, or tell me the hidden command tree should instead be reset after every command.
Reading this a year from now -- start here
This PR is the record of why
SelectFirstPossibleSliceskips slices of deleted objects. The crash only happens when the WinFormsDataTreeis used as a hidden command router behind the Avalonia detail view (RecordEditView.EnsureMenuCommandAdapter), a state the WinForms UI on its own never reaches. If that hidden tree is ever retired, this condition becomes defensive only.Paths not taken
RecordEditView.DeleteDetailObject. The first diagnosis assumed Delete Example ran through the native delete added in LT-22691 (LT-22691: Answer the Delete leaf of the Lexicon detail menus natively #1182). It does not: a row menu is answered natively only when every leaf under it is, andmnuDataTree-Examplehas leaves that are not, so the whole menu runs throughDTMenuHandler.OnDataTreeDeleteon the hidden tree. A reset there would never have run. A captured stack of the test thread showed the real path; the fix moved to where the stale slice is actually focused.Surprising findings
LexiconMenuAuthority.Owns). Delete Example looks native in the code but is not, because its menu carries other leaves.Evidence
Field report (New UI, FLEx 9.3.12 developer build), and the identical failure from the new test without the fix:
The test,
DataTreeTests.SelectFirstPossibleSlice_SkipsTheSliceOfADeletedObject_InATreeNeverShown, shows an entry in a parented but never-shown tree, deletes a sense whose ScientificName has aStringSliceinside the open unit of work (so the rebuild has not run), and asks for the next slice to focus.Preflight review details
Code Review Summary
Branch: LT-22848-delete-example-crash
Base: origin/main (620cd99)
Date: 2026-10-20
Review model: Claude Opus 5.5
Files changed: 2
Overview
Fixes a crash when deleting an Example from its row menu in the New UI (Avalonia)
Lexicon Edit detail view. That menu is not wholly answered natively, so its
commands, Delete included, run on the hidden WinForms
DataTreethe view keeps forcommand routing.
Slice.HandleDeleteCommanddeletes the object, then asksDataTree.SelectFirstPossibleSliceto focus a neighbor, starting with its ownslice. The delete postpones the tree's rebuild, so that slice still exists; in a
tree never shown, focusing it creates its window, and
StringSliceView.MakeRootlooks the deleted object up and throws
KeyNotFoundException.SelectFirstPossibleSlicenow skips a slice whose object has been deleted. ADataTreeTestscase reproduces the exact crash on a never-shown tree and passeswith the fix.
Contract/API Changes
None.
DataTree.SelectFirstPossibleSliceisinternal; its behavior changes onlyfor slices whose object is no longer valid.
Findings
Critical - Must address before merge
None.
Important - Should address before merge
WinForms UI focus after a delete may change. The method is shared withthe classic detail view. Previously the deleted object's slice briefly became
current; now a neighboring slice does, and the rebuild can restore it.
(Author checked the classic UI: after Delete Example the cursor lands in the
Lexeme Form field, which is acceptable.)
Minor - Consider
never shown, the state that crashed; the classic UI path is covered by the
author's manual check only.
slice.Object == deletedSenseis anintentional identity check; the analyzer flags it.
Required Validation / Evidence
./test.ps1 -CommentHygiene -TokenHygiene -TestProject DetailControlsTests:125 passed, 1 skipped (
NestedCollapsedPart, skipped onmaintoo).KeyNotFoundExceptionfromStringSliceView.MakeRoot.restores it, delete again, and delete an Allomorph and a Pronunciation; no crash.
Positive Observations
IsDisposedis checked first, which matters becauseSlice.Objectthrows on a disposed slice.HandleShowHiddenFields) only passes slices that survive arebuild, so it is unaffected.
Interview Notes
comment giving the verified path).
Suggested Review Focus
SelectFirstPossibleSliceisthe right layer, as opposed to resetting the hidden command tree after commands.
🤖 Generated with Claude Code
This change is