Crash using .searchable bound to viewModel and sidebar placement on macOS

On macOS 14.2.1 (23C71), xCode 15.2 (15C500b)

Reported as FB13541783

Demo: https://youtu.be/pm6Nre0RApY

Consider this complete SwiftUI macOS app

//
//  TestSearchStringInViewModelApp.swift
//  TestSearchStringInViewModel
//
//  Created by Damian Mehers on 2024-01-15.
//

import SwiftUI

@main
struct TestSearchStringInViewModelApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

struct ContentView: View {
    // using @Bindable or plain "var" with a Bindable<ViewModel> object in the code does same thing
    @State var viewModel = ViewModel()
    var body: some View {
        NavigationSplitView {
            VStack {
                List(1..<5) { n in
                    Text("\(n)")
                }
                .listStyle(SidebarListStyle())
                // Works if not sidebar or @State searchString
                .searchable(text: $viewModel.searchString, placement: .sidebar)
            }
        } detail: {
            Text("Some detail")
        }
    }
}

@Observable final class ViewModel {
    var searchString = ""
}

When you run it, when you tap “a” into the searchbar two “a”s appear, and when they are both deleted you get a crash:

An uncaught exception was raised
*** -[NSBigMutableString substringWithRange:]: Range {0, 1} out of bounds; string length 0
(
	0   CoreFoundation                      0x00000001820d0570 __exceptionPreprocess + 176
	1   libobjc.A.dylib                     0x0000000181bc1eb4 objc_exception_throw + 60
	2   Foundation                          0x0000000183131930 -[NSString _newSubstringWithRange:zone:] + 0
	3   AppKit                              0x00000001859e6f28 -[NSTextStorage(NSUndo) _undoRedoAttributedSubstringFromRange:] + 140
	4   AppKit                              0x00000001859e6e04 -[NSUndoTyping initWithAffectedRange:textStorage:undoManager:replacementRange:] + 132
	5   AppKit                              0x00000001859e6c6c -[NSTextViewSharedData coalesceInTextView:affectedRange:replacementRange:] + 308
	6   AppKit                              0x00000001859e5f38 -[NSTextView(NSSharing) shouldChangeTextInRanges:replacementStrings:] + 968
	7   AppKit                              0x00000001861f9d18 -[NSTextView performValidatedReplacementInRange:withAttributedString:] + 196
	8   SwiftUI                             0x00000001ae4223d8 OUTLINED_FUNCTION_6 + 2648
	9   SwiftUI                             0x00000001ae53c724 OUTLINED_FUNCTION_1 + 8004
	10  SwiftUI                             0x00000001ae53bfd4 OUTLINED_FUNCTION_1 + 6132
	11  SwiftUI                             0x00000001ae53ba8c OUTLINED_FUNCTION_1 + 4780
	12  SwiftUI                             0x00000001ae53acb8 OUTLINED_FUNCTION_1 + 1240
	13  SwiftUI                             0x00000001aced8030 OUTLINED_FUNCTION_38 + 907680
	14  SwiftUI                             0x00000001ad00cae4 OUTLINED_FUNCTION_38 + 2171988
	15  SwiftUI                             0x00000001ad0eacc4 objectdestroy.127Tm + 5004
	16  SwiftUI                             0x00000001ae4045e0 OUTLINED_FUNCTION_2 + 31536
	17  SwiftUI                             0x00000001ad0084cc OUTLINED_FUNCTION_38 + 2154044
	18  SwiftUI                             0x00000001acff47b8 OUTLINED_FUNCTION_38 + 2072872
	19  SwiftUI                             0x00000001ad17aa28 objectdestroy.2265Tm + 6976
	20  AttributeGraph                      0x00000001aea237a4 _ZN2AG5Graph11UpdateStack6updateEv + 512
	21  AttributeGraph                      0x00000001aea23fe0 _ZN2AG5Graph16update_attributeENS_4data3ptrINS_4NodeEEEj + 424
	22  AttributeGraph                      0x00000001aea32828 _ZN2AG8Subgraph6updateEj + 848
	23  SwiftUI                             0x00000001ae32a2dc OUTLINED_FUNCTION_5 + 12088
	24  SwiftUI                             0x00000001adc8b68c OUTLINED_FUNCTION_10 + 6360
	25  SwiftUI                             0x00000001ad58fd6c OUTLINED_FUNCTION_58 + 1312
	26  SwiftUI                             0x00000001ad58fc34 OUTLINED_FUNCTION_58 + 1000
	27  libswiftObservation.dylib           0x0000000222ed8558 $s11Observation0A8TrackingV08_installB0_7willSet03didE0yAC_yACYbcSgAGtFZAC2IdOAC5EntryVXEfU_yyYbcfU2_TATm + 48
	28  libswiftObservation.dylib           0x0000000222ed8670 $sIegh_ytIeghr_TRTA + 28
	29  libswiftObservation.dylib           0x0000000222ed682c $s11Observation0A9RegistrarV7ContextV7willSet_7keyPathyx_s03KeyG0Cyxq_GtAA10ObservableRzr0_lFTf4dnn_n + 568
	30  libswiftObservation.dylib           0x0000000222ed725c $s11Observation0A9RegistrarV7willSet_7keyPathyx_s03KeyF0Cyxq_GtAA10ObservableRzr0_lFTf4dnn_n + 60
	31  libswiftObservation.dylib           0x0000000222ed2158 $s11Observation0A9RegistrarV12withMutation2of7keyPath_q0_x_s03KeyG0Cyxq_Gq0_yKXEtKAA10ObservableRzr1_lF + 80
	32  TestSearchStringInViewModel         0x000000010018dbf4 $s27TestSearchStringInViewModel0eF0C12withMutation7keyPath_q_s03KeyJ0CyACxG_q_yKXEtKr0_lF + 284
	33  TestSearchStringInViewModel         0x000000010018d5b8 $s27TestSearchStringInViewModel0eF0C06searchC0SSvs + 156
	34  TestSearchStringInViewModel         0x000000010018d504 $s27TestSearchStringInViewModel0eF0C06searchC0SSvpACTk + 88
	35  libswiftCore.dylib                  0x000000019198c560 $ss26NonmutatingWritebackBufferCfD + 312
	36  libswiftCore.dylib                  0x0000000191bbddb0 _swift_release_dealloc + 56
	37  libswiftCore.dylib                  0x0000000191bbea8c _ZN5swift9RefCountsINS_13RefCountBitsTILNS_19RefCountInlinednessE1EEEE15doDecrementSlowILNS_13PerformDeinitE1EEEbS3_j + 136
	38  libswiftCore.dylib                  0x000000019198dd2c swift_setAtReferenceWritableKeyPath + 244
	39  SwiftUI                             0x00000001ad28b210 OUTLINED_FUNCTION_7 + 1520
	40  SwiftUI                             0x00000001ad28b32c OUTLINED_FUNCTION_7 + 1804
	41  SwiftUI                             0x00000001ae27b25c OUTLINED_FUNCTION_1 + 9376
	42  SwiftUI                             0x00000001ad28b128 OUTLINED_FUNCTION_7 + 1288
	43  SwiftUI                             0x00000001adb31b08 OUTLINED_FUNCTION_0 + 1256
	44  SwiftUI                             0x00000001ae49dac8 objectdestroy.2Tm + 3400
	45  SwiftUI                             0x00000001adb31b08 OUTLINED_FUNCTION_0 + 1256
	46  SwiftUI                             0x00000001adb33b6c OUTLINED_FUNCTION_0 + 9548
	47  SwiftUI                             0x00000001adb31b08 OUTLINED_FUNCTION_0 + 1256
	48  SwiftUI                             0x00000001adb32f34 OUTLINED_FUNCTION_0 + 6420
	49  SwiftUI                             0x00000001adb332dc OUTLINED_FUNCTION_0 + 7356
	50  SwiftUI                             0x00000001adb31b08 OUTLINED_FUNCTION_0 + 1256
	51  SwiftUI                             0x00000001adb32f34 OUTLINED_FUNCTION_0 + 6420
	52  SwiftUI                             0x00000001adb332dc OUTLINED_FUNCTION_0 + 7356

I didn't ask a question! My question is, am I doing something wrong?

Crash using .searchable bound to viewModel and sidebar placement on macOS
 
 
Q