dagger/dagger · error

no LLM session active

Error message

no LLM session active

What it means

ExportChanges performs the ctrl+s action: exporting the workspace's pending overlay edits to the local Git workspace. It requires an active LLM session; when s.llm is nil there is nothing to export and the error is returned.

Source

Thrown at internal/cmd/dagger/llm.go:485

			var buf strings.Builder
			patchpreview.Summarize(idtui.NewOutput(&buf), entries, width)
			return buf.String()
		},
		KeyMap: []key.Binding{
			key.NewBinding(key.WithKeys("ctrl+s"), key.WithHelp("ctrl+s", "save")),
			key.NewBinding(key.WithKeys("ctrl+u"), key.WithHelp("ctrl+u", "reset")),
		},
	})
	return nil
}

// ExportChanges writes the workspace's pending overlay edits to its local Git
// workspace (Workspace.export), then refreshes the changes preview. It is the
// ctrl+s action; export fails clearly when the workspace cannot persist (a
// remote ref, a synthetic workspace, or a local dir with no Git root).
func (s *LLMSession) ExportChanges(ctx context.Context) error {
	if s.llm == nil {
		return fmt.Errorf("no LLM session active")
	}
	if err := s.llm.Workspace().Export(ctx); err != nil {
		return err
	}
	// The exported edits now live on disk, so rebind the live workspace: the
	// overlay the agent accumulated is now redundant with the files
	// themselves, and carrying it forward would re-diff already-saved content
	// as pending changes. Rebinding also drops it from the next save —
	// portableID emits only the current binding. Export bumps the client's
	// workspace read epoch, so reads after this point see the saved content
	// rather than a snapshot cached earlier in the session. Sync eagerly so a
	// failure surfaces here rather than corrupting later saves.
	rebound, err := s.llm.WithWorkspace(s.dag.CurrentWorkspace()).Sync(ctx)
	if err != nil {
		return fmt.Errorf("rebind workspace after export: %w", err)
	}
	if err := s.updateLLM(rebound); err != nil {
		return err

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Start the session (send a prompt via WithPrompt) before calling ExportChanges
  2. Guard the call: skip export when no session is active
  3. Re-create or reinitialize the session if it was reset unexpectedly

Example fix

// before
session.ExportChanges(ctx) // panics-free but errors: no LLM session active
// after
if session.LLM() != nil {
    session.ExportChanges(ctx)
}
Defensive patterns

Strategy: type-guard

Validate before calling

if session == nil || !session.Active() { return errors.New("start a prompt before exporting changes") }

Type guard

func (s *LLMSession) HasLLM() bool { return s != nil && s.llm != nil }

Try / catch

if err := session.ExportChanges(ctx); err != nil && err.Error() == "no LLM session active" { /* start session or skip */ }

Prevention

When it happens

Trigger: Calling LLMSession.ExportChanges before any prompt/session was started (s.llm == nil), e.g. via a keybinding or API call on a freshly constructed session.

Common situations: Calling ExportChanges in a script or TUI binding before the first prompt; resetting a session then attempting to export; UI state desync after session teardown.

Related errors


AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05). Data as JSON: /api/errors/679986215262d474. Report an issue: GitHub.