charmbracelet/crush · error

no sessions found to continue

Error message

no sessions found to continue

What it means

When --continue is used without an ID (useLast), resolveSession calls client.ListSessions and fails if the listing errors or returns zero sessions. Both conditions collapse into this one message, so an empty workspace and an RPC failure look identical to the user.

Source

Thrown at internal/cmd/run.go:687

// 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")
	}
}

// resolveSessionByID resolves a session ID that may be a full UUID or a hash
// prefix returned by crush session list.
func resolveSessionByID(ctx context.Context, c *client.Client, wsID, id string) (*proto.Session, error) {
	if sess, err := c.GetSession(ctx, wsID, id); err == nil {

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Omit --continue so a new session is created automatically.
  2. Run an interactive `crush` session once (or any successful run) to create a session, then use --continue.
  3. Ensure --data-dir / HOME point at the directory that actually holds your sessions.
  4. If sessions should exist, check the server is up and the DB file is readable.

Example fix

// before
crush run --continue "do the thing"   # no sessions yet
// after
crush run "do the thing"              # creates a new session
Defensive patterns

Strategy: validation

Validate before calling

sessions, err := c.ListSessions(ctx, wsID)
if err != nil || len(sessions) == 0 {
    // no sessions yet — don't pass --continue
    fmt.Println("no sessions exist; starting fresh")
}

Type guard

func hasContinuableSession(sessions []proto.Session) bool {
    for _, s := range sessions {
        if s.ParentSessionID == "" {
            return true
        }
    }
    return false
}

Try / catch

out, err := runCrush("run", maybeContinueFlag, prompt)
if err != nil && strings.Contains(out, "no sessions found to continue") {
    out, err = runCrush("run", prompt) // fresh session
}

Prevention

When it happens

Trigger: Running `crush run --continue "prompt"` (continue-last behavior) in a workspace that has never had a session, after the DB was wiped/moved, or when ListSessions fails due to server/connection issues.

Common situations: First-ever run with --continue; pointing --data-dir at an empty directory; CI environment with a fresh HOME so the global config/cache dir has no sessions; server unreachable.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/384286872f89c6e0. Report an issue: GitHub.