charmbracelet/crush · error

cannot continue an agent tool session: %s

Error message

cannot continue an agent tool session: %s

What it means

resolveSession rejects --continue/--session targeting a session created by the agent (task) tool. Sub-sessions spawned via the agent tool are internal worker sessions and are not valid continuation roots, so continuing them is blocked by design.

Source

Thrown at internal/app/app.go:242

// ReportCurrentSession tells herdr which session the user is now
// viewing so it can persist a resumable reference for the pane. Safe
// to call when not running inside a herdr pane; the underlying client
// is nil-safe. Call this whenever the active session changes (load,
// new, or select).
func (app *App) ReportCurrentSession(sessionID string) {
	app.herdrClient.SetSessionID(sessionID)
}

// resolveSession resolves which session to use for a non-interactive run
// If continueSessionID is set, it looks up that session by ID
// If useLast is set, it returns the most recently updated top-level session
// Otherwise, it creates a new session
func (app *App) resolveSession(ctx context.Context, continueSessionID string, useLast bool) (session.Session, error) {
	switch {
	case continueSessionID != "":
		if app.Sessions.IsAgentToolSession(continueSessionID) {
			return session.Session{}, fmt.Errorf("cannot continue an agent tool session: %s", continueSessionID)
		}
		sess, err := app.Sessions.Get(ctx, continueSessionID)
		if err != nil {
			return session.Session{}, fmt.Errorf("session not found: %s", continueSessionID)
		}
		if sess.ParentSessionID != "" {
			return session.Session{}, fmt.Errorf("cannot continue a child session: %s", continueSessionID)
		}
		return sess, nil

	case useLast:
		sess, err := app.Sessions.GetLast(ctx)
		if err != nil {
			return session.Session{}, fmt.Errorf("no sessions found to continue")
		}
		return sess, nil

	default:

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Use the top-level (parent) session ID instead of the agent-tool sub-session ID.
  2. If scripting, filter sessions to those where IsAgentToolSession(id) is false before choosing one.
  3. Start a new session if the intent was to resume work not tied to a top-level conversation.

Example fix

// before
app.RunNonInteractive(ctx, "abc123-agent-subsesson-id", prompt, quiet)

// after
if app.Sessions.IsAgentToolSession(id) {
    id = parentSessionID // resolve to the top-level session
}
app.RunNonInteractive(ctx, id, prompt, quiet)
Defensive patterns

Strategy: validation

Validate before calling

if app.Sessions.IsAgentToolSession(sessionID) {
    return fmt.Errorf("%s is an agent-tool session; use its parent instead", sessionID)
}

Try / catch

if err != nil {
    if strings.HasPrefix(err.Error(), "cannot continue an agent tool session") {
        // resolve and retry with the parent session ID
    }
    return err
}

Prevention

When it happens

Trigger: Calling RunNonInteractive (or the CLI equivalent) with continueSessionID set to a session ID that IsAgentToolSession reports as an agent-tool-created session — e.g. copying a sub-agent's session ID from the UI or DB.

Common situations: Users grabbing an internal sub-agent session ID from logs/database; scripts that enumerate all sessions and pick the latest, accidentally selecting an agent-tool session.

Related errors


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