charmbracelet/crush · error
cannot continue a child session: %s
Error message
cannot continue a child session: %s
What it means
After a session is fetched successfully, resolveSession rejects it if ParentSessionID is non-empty. Child sessions are created for sub-agents/tasks spawned from a parent run and are not meant to be resumed directly, so continuing one is blocked with this error.
Source
Thrown at internal/cmd/run.go:680
label, modelID, strings.Join(names, ", "),
)
}
return matches[0], nil
}
// resolveSession returns the session to use for a non-interactive run.
// If continueSessionID is set it fetches that session; if useLast is set it
// returns the most recently updated top-level session; otherwise it creates a
// new one.
func resolveSession(ctx context.Context, c *client.Client, wsID, continueSessionID string, useLast bool) (*proto.Session, error) {
switch {
case continueSessionID != "":
sess, err := c.GetSession(ctx, wsID, continueSessionID)
if err != nil {
return nil, fmt.Errorf("session not found: %s", continueSessionID)
}
if sess.ParentSessionID != "" {
return nil, fmt.Errorf("cannot continue a child session: %s", continueSessionID)
}
return sess, nil
case useLast:
sessions, err := c.ListSessions(ctx, wsID)
if err != nil || len(sessions) == 0 {
return nil, fmt.Errorf("no sessions found to continue")
}
last := sessions[0]
for _, s := range sessions[1:] {
if s.UpdatedAt > last.UpdatedAt && s.ParentSessionID == "" {
last = s
}
}
return &last, nil
default:
return c.CreateSession(ctx, wsID, "non-interactive")View on GitHub (pinned to 7944b8e522)
Solutions
- Find the parent session ID (the child's ParentSessionID field) and pass that to --continue instead.
- List sessions and choose one without a parent (a top-level session).
- If you need the child's context, resume the parent session which contains the child's history.
Example fix
// before crush run --continue <child-session-id> "continue" // after # resume the parent of that child session instead crush run --continue <parent-session-id> "continue"
Defensive patterns
Strategy: validation
Validate before calling
sess, err := c.GetSession(ctx, wsID, contID)
if err == nil && sess.ParentSessionID != "" {
return fmt.Errorf("refusing to continue child session %s; use parent %s", contID, sess.ParentSessionID)
} Type guard
func isTopLevel(s proto.Session) bool { return s.ParentSessionID == "" } Try / catch
sess, err := resolveSession(ctx, c, wsID, contID, false)
if err != nil && strings.HasPrefix(err.Error(), "cannot continue a child session:") {
// resolve the parent and retry
parentID := childToParent[contID]
sess, err = resolveSession(ctx, c, wsID, parentID, false)
} Prevention
- Filter session lists to ParentSessionID == "" before offering IDs for --continue.
- Store parent IDs, not child/task IDs, in scripts and CI workflows.
When it happens
Trigger: Calling `crush run --continue <childSessionID>` where the session record has a non-empty ParentSessionID, i.e. the ID belongs to a task/sub-agent session rather than a top-level session.
Common situations: Copying a session ID from a child task in the session list or logs instead of the parent; picking the wrong row when several sessions share a similar name; scripting against session IDs harvested from internal message records.
Related errors
- ${sessionList} Use more characters or the full hash
- cannot continue an agent tool session: %s
- session not found: %s
- cannot continue a child session: %s
- no sessions found to continue
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/439069802ee62348.
Report an issue: GitHub.