affaan-m/ECC · error · anyhow::Error
Session {} has no attached worktree
Error message
Session {} has no attached worktree What it means
The merge_session_worktree function, after verifying the session is in a terminal state, requires an attached worktree to merge. If session.worktree is None, there is nothing to merge. This happens when the session was created without a worktree (e.g., a main-repo session) or the worktree was already removed.
Source
Thrown at ecc2/src/session/manager.rs:1793
cleanup_worktree: bool,
) -> Result<WorktreeMergeOutcome> {
let session = resolve_session(db, id)?;
if matches!(
session.state,
SessionState::Pending | SessionState::Running | SessionState::Idle | SessionState::Stale
) {
anyhow::bail!(
"Cannot merge active session {} while it is {}",
session.id,
session.state
);
}
let worktree = session
.worktree
.clone()
.ok_or_else(|| anyhow::anyhow!("Session {} has no attached worktree", session.id))?;
let outcome = crate::worktree::merge_into_base(&worktree)?;
if cleanup_worktree {
crate::worktree::remove(&worktree)?;
db.clear_worktree(&session.id)?;
}
Ok(WorktreeMergeOutcome {
session_id: session.id,
branch: outcome.branch,
base_branch: outcome.base_branch,
already_up_to_date: outcome.already_up_to_date,
cleaned_worktree: cleanup_worktree,
})
}
pub async fn rebase_session_worktree(db: &StateStore, id: &str) -> Result<WorktreeRebaseOutcome> {
let session = resolve_session(db, id)?;View on GitHub (pinned to 01e15490f0)
Solutions
- Check session.worktree.is_some() before calling merge_session_worktree
- If the worktree was already cleaned up, treat the operation as a no-op success
- Ensure sessions that need merging are created with a worktree from the start
- Avoid calling merge twice on the same session — track which sessions have been merged
Example fix
// before
merge_session_worktree(db, &id, true).await?;
// after
let session = resolve_session(db, &id)?;
if session.worktree.is_none() {
tracing::info!("session {} has no worktree to merge", id);
return Ok(WorktreeMergeOutcome::noop(id));
}
merge_session_worktree(db, &id, true).await?; Defensive patterns
Strategy: validation
Validate before calling
let session = resolve_session(db, id)?;
if session.worktree.is_none() {
return Ok(WorktreeMergeOutcome::noop(id));
} Type guard
fn has_worktree(session: &Session) -> bool {
session.worktree.is_some()
} Try / catch
match merge_session_worktree(db, id, cleanup).await {
Ok(outcome) => Ok(outcome),
Err(e) if e.to_string().contains("no attached worktree") => {
Ok(WorktreeMergeOutcome::noop(id))
}
Err(e) => Err(e),
} Prevention
- Track which sessions have worktrees in the caller to avoid merge on worktreeless sessions
- Treat 'no worktree' as a no-op success rather than an error in automated pipelines
- Ensure sessions that need merging are created with a worktree from the start
When it happens
Trigger: Calling merge_session_worktree on a session where session.worktree is None — the session was created without a worktree branch or the worktree was already cleaned up.
Common situations: Session ran in the main repository without a worktree. Worktree was already merged and removed by a previous call. Worktree path was manually deleted outside ECC.
Related errors
- Cannot merge active session {} while it is {}
- Session not found: {session_id}
- Cannot rebase active session {} while it is {}
- Session not found: {id}
- git merge-tree failed: {stderr}
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/c39d7a95d4f6ee22.
Report an issue: GitHub.