Hmbown/CodeWhale · warning · std::io::Error
Cannot open session : its queued input is already open in…
Error message
Cannot open session {session_id}: its queued input is already open in another window, or its previous writes are still finishing ({error}) What it means
Raised when opening a session file requires an exclusive write lease (`fd_lock::RwLock::try_write`) but another process/window already holds it, or a prior writer has not released the descriptor. The original lock error's kind is preserved and its text is embedded in the message so the user knows the session is contended, not corrupted.
Solutions
- Close the other window/process holding the session, then retry.
- Wait a moment and retry — a finishing writer releases the lock on its own.
- Find the lingering process (e.g. `lsof`/`fuser` on the session file) and terminate it before reopening.
- Retry with backoff if your tooling opens sessions programmatically.
Defensive patterns
Strategy: retry
Validate before calling
ps_aux = /* check no other process of yours has this session open */;
Try / catch
for attempt in 0..5 {
match manager.open_session(id) {
Err(e) if e.to_string().contains("already open in another window") => {
std::thread::sleep(Duration::from_millis(250 * (attempt + 1)));
}
other => { other?; break; }
}
} Prevention
- Open a given session in only one window at a time.
- After a crash, wait briefly before reopening so the stale lock clears.
- Detect and terminate leftover TUI processes before scripted resumes.
When it happens
Trigger: Calling the session-open path while a second window has the same session_id open, or immediately after a crash while the previous writer's file handle/lock is still held.
Common situations: Opening the same session in two terminal windows; a crashed TUI leaving a stale lock briefly; concurrent background write finishing while a resume is attempted.
Related errors
- session ' ' is open in an interactive Codewhale session…
- Another pet owner is running
- Checkpoint schema v is newer than supported v
- control socket already live at
- Fleet ledger lock was replaced; reopen the workspace before…
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/3612a5899e7c6e79.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/session_manager.rs:2127
/// resume. A per-write lock is insufficient: the second editor's stale
/// snapshot would overwrite the first as soon as its write completed.
pub fn acquire_offline_queue_lease(
&self,
session_id: &str,
) -> io::Result<std::sync::Arc<OfflineQueueLease>> {
let session_id = self.validated_session_id(session_id)?.to_string();
let directory = self.checkpoints_dir();
fs::create_dir_all(&directory)?;
let path = directory.join(format!("{session_id}.offline_queue.lock"));
let file = fs::OpenOptions::new()
.create(true)
.truncate(false)
.read(true)
.write(true)
.open(path)?;
let mut lock = fd_lock::RwLock::new(file);
let guard = lock.try_write().map_err(|error| {
io::Error::new(
error.kind(),
format!("Cannot open session {session_id}: its queued input is already open in another window, or its previous writes are still finishing ({error})"),
)
})?;
// fd-lock's guard borrows its owner. Retain the underlying descriptor
// instead so this lease can travel with asynchronous writes. Forgetting
// this non-owning guard keeps the OS lock held; the final Arc explicitly
// unlocks in Drop. The OS also releases it when the process crashes.
std::mem::forget(guard);
Ok(std::sync::Arc::new(OfflineQueueLease {
session_id,
_file: lock.into_inner(),
}))
}
/// Park this session's offline queue (queued + draft messages).
///
/// Queues are keyed per session (`checkpoints/<session_id>.offline_queue.json`)View on GitHub (pinned to 433685b202)