charmbracelet/crush · error

no sessions found

Error message

no sessions found

What it means

`crush session last` looks up the most recent session by listing all sessions from the SQLite session store and taking the first entry. When the list comes back empty it throws `no sessions found` because there is no 'last' session to display. It is not a transport or DB failure — the query succeeded but the database holds zero session rows.

Source

Thrown at internal/cmd/session.go:378

func runSessionLast(cmd *cobra.Command, _ []string) error {
	event.SetNonInteractive(true)

	ctx, svc, cleanup, err := sessionSetup(cmd)
	if err != nil {
		return err
	}
	defer cleanup()

	event.SessionLastShown(sessionLastJSON)

	list, err := svc.sessions.List(ctx)
	if err != nil {
		return fmt.Errorf("failed to list sessions: %w", err)
	}

	if len(list) == 0 {
		return fmt.Errorf("no sessions found")
	}

	sess := list[0]

	msgs, err := svc.messages.List(ctx, sess.ID)
	if err != nil {
		return fmt.Errorf("failed to list messages: %w", err)
	}

	msgPtrs := messagePtrs(msgs)
	if sessionLastJSON {
		return outputSessionJSON(cmd.OutOrStdout(), sess, msgPtrs)
	}
	return outputSessionHuman(ctx, svc.cfg, sess, msgPtrs)
}

const (
	sessionOutputWidth     = 80

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Run an interactive session (`crush`) at least once so a session row is created, then retry `crush session last`.
  2. Use `crush sessions list` to confirm whether any sessions exist for the current data directory.
  3. If you expected sessions, check that you are not pointing at an unexpected --data-dir; the session store is per data directory.
  4. If scripting, treat empty history as a normal case and fall back to creating a new session instead of calling `session last`.

Example fix

// before
cmd := exec.Command("crush", "session", "last")
out, err := cmd.Output()
// after
list := exec.Command("crush", "sessions", "list")
listOut, _ := list.Output()
if len(bytes.TrimSpace(listOut)) == 0 {
    fmt.Println("no sessions yet; starting a new one")
    return
}
out, err := exec.Command("crush", "session", "last").Output()
Defensive patterns

Strategy: fallback

Validate before calling

// Check for existing sessions before requesting 'last'
out, err := exec.Command("crush", "sessions", "list").Output()
if err != nil {
    log.Fatal(err)
}
if len(bytes.TrimSpace(out)) == 0 || strings.Contains(string(out), "No sessions") {
    fmt.Println("no sessions exist yet")
    return
}

Type guard

func hasSessions(listOut []byte) bool {
    return len(bytes.TrimSpace(listOut)) > 0 &&
        !strings.Contains(strings.ToLower(string(listOut)), "no sessions")
}

Try / catch

out, err := exec.Command("crush", "session", "last").CombinedOutput()
if err != nil {
    if strings.Contains(string(out), "no sessions found") {
        fmt.Println("No sessions yet — run `crush` to start one.")
        return
    }
    log.Fatalf("unexpected error: %v: %s", err, out)
}

Prevention

When it happens

Trigger: Running `crush session last` (or `crush sessions last`) in a project/data-dir where no session has ever been created, i.e. `svc.sessions.List(ctx)` returned an empty slice at internal/cmd/session.go:377. Also occurs after wiping the data directory (deleting ~/.local/share/crush or a custom --data-dir) or pointing at a fresh data-dir that has no sessions yet.

Common situations: New user runs `session last` before ever starting a chat; CI or scripts query `session last` against an isolated --data-dir that was never used; user removed the data directory or moved machines without migrating the DB.

Related errors


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