sinelaw/fresh · error
active window present
Error message
active window present
What it means
Panic from `.expect("active window present")` in `jump_to_bookmark` (bookmark_actions.rs:92). Jumping to a bookmark whose buffer is not the active one checks whether that buffer still exists in the active window's buffer map; the expect asserts the active window exists. It panics if the bookmark action is dispatched while `self.active_window` does not resolve to an entry in `self.windows`.
Solutions
- Replace the expect with a guard: if the active window is missing, either drop the action or show the 'buffer gone' status message.
- Make window close always update `self.active_window` to a remaining window.
- Prune bookmarks whose buffer/window no longer exists when windows close.
- Add a regression test jumping to a bookmark after closing all windows.
Example fix
// before
.map(|w| &w.buffers)
.expect("active window present")
.contains_key(&bookmark.buffer_id)
// after
let Some(active) = self.windows.get(&self.active_window) else {
self.set_status_message(t!("bookmark.buffer_gone", key = key).to_string());
return;
};
if active.buffers.contains_key(&bookmark.buffer_id) { ... } Defensive patterns
Strategy: validation
Validate before calling
if !self.windows.contains_key(&self.active_window) {
self.set_status_message(t!("bookmark.buffer_gone", key = key).to_string());
return;
} Type guard
fn can_jump_to_bookmark(app: &App, bm: &Bookmark) -> bool {
app.windows.get(&app.active_window)
.map(|w| w.buffers.contains_key(&bm.buffer_id))
.unwrap_or(false)
} Try / catch
std::panic::catch_unwind(AssertUnwindSafe(|| self.jump_to_bookmark(key))).map_err(|_| self.set_status_message("bookmark unavailable".into())); Prevention
- Validate bookmark targets (window + buffer exist) before executing jump actions.
- Clean up bookmarks belonging to a window when that window is removed.
- Prefer Option-based lookup with a status-message fallback over expect in user-action handlers.
- Test bookmark jumps immediately after closing windows.
When it happens
Trigger: `handle_action` dispatches `jump_to_bookmark` for a bookmark with `buffer_id != self.active_buffer()`, and `self.windows.get(&self.active_window)` is None — active window closed/removed but `active_window` still references it.
Common situations: Invoking a bookmark jump via keybinding/command palette right after window teardown; stale bookmark registry pointing into a closed window; action queue replaying actions after window close.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- active window present
- active window must have a populated split layout
- active window present
- active window present
- has_other_tab
AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13).
Data as JSON: /api/errors/3b9369c7bb1f9875.
Report an issue: GitHub.
Appendix: source
Thrown at crates/fresh-editor/src/app/bookmark_actions.rs:92
///
/// Stays on `impl Editor` because the body fires plugin hooks
/// (`apply_event_to_active_buffer`) and orchestrates cross-cutting
/// state (active-buffer switch, viewport recentering). Moving it
/// to `impl Window` waits for plugin-hook firing to be available
/// from `Window`.
pub(super) fn jump_to_bookmark(&mut self, key: char) {
let Some(bookmark) = self.active_window_mut().bookmarks.get(key) else {
self.set_status_message(t!("bookmark.not_set", key = key).to_string());
return;
};
// Switch to the buffer if needed, or forget the bookmark if it's gone.
if bookmark.buffer_id != self.active_buffer() {
if self
.windows
.get(&self.active_window)
.map(|w| &w.buffers)
.expect("active window present")
.contains_key(&bookmark.buffer_id)
{
self.set_active_buffer(bookmark.buffer_id);
} else {
self.set_status_message(t!("bookmark.buffer_gone", key = key).to_string());
self.active_window_mut().bookmarks.remove(key);
return;
}
}
// Move cursor to bookmark position
let cursor = *self.active_cursors().primary();
let cursor_id = self.active_cursors().primary_id();
let state = self.active_state_mut();
let new_pos = bookmark.position.min(state.buffer.len());
let event = Event::MoveCursor {
cursor_id,View on GitHub (pinned to 67894ca546)