diff --git a/src/ui/windows/console_tab.cpp b/src/ui/windows/console_tab.cpp index 66bd58f..575512f 100644 --- a/src/ui/windows/console_tab.cpp +++ b/src/ui/windows/console_tab.cpp @@ -511,8 +511,7 @@ void ConsoleTab::renderToolbar(ConsoleCommandExecutor& exec) // Clear button if (TactileButton(TR("console_clear"), ImVec2(0, 0), schema::UI().resolveFont("button"))) { - clear(); - selection_.clear(); + clear(); // also drops the stale visible_indices_ + selection (see ConsoleTab::clear) } ImGui::SameLine(); @@ -1183,9 +1182,9 @@ void ConsoleTab::drawOutputContextMenu() } ImGui::Separator(); if (ImGui::MenuItem(TR("console_clear_console"))) { - // View-only clear (main thread) — drop the visible lines and the selection. - model_.clear(); - selection_.clear(); + // View-only clear — route through clear() so the stale visible_indices_/selection are dropped too + // (a bare model_.clear() mid-frame would leave renderOutput() indexing the emptied model_ → crash). + clear(); } ImGui::EndPopup(); } @@ -2004,6 +2003,12 @@ void ConsoleTab::clear() // View-only clear (main thread). The executor keeps its own log cursors, so new output // still appends. The "cleared" line is ingested and appears on the next frame's drain. model_.clear(); + // visible_indices_ was computed at the top of render() (line 311), BEFORE the toolbar's Clear button + // ran; those indices now point past the emptied model_. renderOutput() (this same frame, after the + // toolbar) indexes model_[visible_indices_[vi]] — so drop them (and the selection, which also holds + // line indices) here to avoid an out-of-bounds crash. computeVisibleLines() rebuilds them next frame. + visible_indices_.clear(); + selection_.clear(); stop_confirm_pending_ = false; // a pending 'stop' confirmation is cancelled by clearing addLine(TR("console_cleared"), ConsoleChannel::Info); }