Hmbown/CodeWhale · error
Failed to sync thread session
Error message
Failed to sync thread session: {e} What it means
Raised while loading a thread when restoring its persisted history onto a freshly spawned engine fails: the runtime sends an `Op::SyncSession` message (restored session messages, optional system prompt, model, workspace, mode) and the engine's channel send returns Err. That happens only when the engine's receiver is gone — the just-spawned engine task already terminated — or the send otherwise fails with error `{e}`.
Solutions
- Read `{e}` for the underlying send failure; check logs for an engine startup panic and fix its config cause.
- Retry opening the thread — a new engine is spawned on the next attempt.
- Validate tools/advisor/exec-policy settings in the config that the engine consumes at startup.
- Avoid opening threads during application shutdown; free memory if OOM killed the worker.
Defensive patterns
Strategy: retry
Try / catch
match open_thread(&thread_id).await {
Err(e) if e.to_string().contains("Failed to sync thread session") => {
// engine died at startup: check logs, fix config, then reopen the thread
}
r => r?,
} Prevention
- Validate tools/advisor/exec-policy engine config that runs at engine startup.
- Fix any engine startup panics in logs before reopening threads.
- Do not open threads while the app is shutting down.
- Watch memory usage so fresh engine tasks are not OOM-killed.
When it happens
Trigger: Opening/reloading a thread whose restored session messages or system prompt are non-empty, when `engine.send(Op::SyncSession {...}).await` returns Err because the engine worker died immediately after spawn (panic at startup, invalid engine config) or the channel was closed.
Common situations: Engine worker panics during initialization (bad tools config, invalid exec policy engine); app shutting down while threads are being opened; resource exhaustion (OOM) killing the freshly spawned task; a config reload spawning an engine that fails to start.
Related errors
- Failed to trigger compaction: engine operation channel…
- Compaction lifecycle task ended before acknowledgement
- engine event channel closed before turn
- Runtime engine shutdown failed
- Turn lifecycle task ended before acknowledgement
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/4b35b8c10ccae946.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/runtime_threads.rs:11084
.map(|s| SystemPrompt::Text(s.clone()));
if !session_messages.is_empty() || sys_prompt.is_some() {
engine
.send(Op::SyncSession {
session_id: thread.session_id.clone(),
messages: session_messages,
system_prompt: sys_prompt,
system_prompt_override: thread.system_prompt.is_some(),
model: route_model.clone(),
workspace: thread.workspace.clone(),
mode: RuntimePolicyProjection::from_persisted(
&thread.mode,
thread.permission_posture.as_deref(),
thread.auto_approve,
)
.mode,
})
.await
.map_err(|e| anyhow!("Failed to sync thread session: {e}"))?;
}
let mut active = self.active.lock().await;
if let Some(winner) = active
.engines
.get(&thread.id)
.map(|state| state.engine.clone())
{
touch_lru(&mut active.lru, &thread.id);
drop(active);
engine.cancel_with_reason(crate::core::engine::CancelReason::Internal);
let _ = engine.try_send(Op::Shutdown);
return Ok(winner);
}
// Atomically compare the record used for construction with the latest
// durable record while holding the same active -> thread lock order as
// updates. A concurrent workspace/model/session/policy change makesView on GitHub (pinned to 73e0f67d83)