charmbracelet/crush · error
failed to get last assistant message: %w
Error message
failed to get last assistant message: %w
What it means
restoreModelFromSession reads the last assistant message via app.Messages.GetLastAssistantMessage to restore provider/model on --continue/--last runs. sql.ErrNoRows is treated as success (nothing to restore), but any other DB error is wrapped with this message. It indicates a storage failure while fetching session history.
Source
Thrown at internal/app/app.go:459
if app.AgentCoordinator == nil {
return fmt.Errorf("agent configuration is missing")
}
return app.AgentCoordinator.UpdateModels(ctx)
}
// restoreModelFromSession reads the last assistant message in the
// session and, if it used a different provider/model than the current
// config, overrides the preferred model in-memory (non-persistent)
// provided the provider/model is still available. This ensures that
// continuing a session uses the same model that produced the last
// response.
func (app *App) restoreModelFromSession(ctx context.Context, sessionID string) error {
lastMsg, err := app.Messages.GetLastAssistantMessage(ctx, sessionID)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil
}
return fmt.Errorf("failed to get last assistant message: %w", err)
}
if lastMsg.Provider == "" || lastMsg.Model == "" {
return nil
}
cfg := app.config.Config()
currentLarge := cfg.Models[config.SelectedModelTypeLarge]
if currentLarge.Provider == lastMsg.Provider && currentLarge.Model == lastMsg.Model {
return nil
}
if !cfg.IsModelAvailable(lastMsg.Provider, lastMsg.Model) {
slog.Debug("Skipping model restoration: provider/model not available",
"provider", lastMsg.Provider,
"model", lastMsg.Model)
return nil
}
View on GitHub (pinned to 7944b8e522)
Solutions
- Check the SQLite DB file is readable and the disk has space
- Move the corrupt DB aside so a fresh one is created
- Run crush once with SLOG_LEVEL=debug to identify the migration/query failure
- Reinstall/upgrade crush if migrations are out of sync with the DB version
Defensive patterns
Strategy: validation
Validate before calling
if _, err := os.Stat(dbPath); err != nil {
return fmt.Errorf("session DB missing/corrupt: %s", dbPath)
}
// only continue sessions that actually have history
if !sessionHasAssistantMessages(sessionID) {
// proceed without restore — crush treats ErrNoRows as no-op
} Try / catch
if err := app.RunNonInteractive(ctx, w, prompt, "", "", true, contID, useLast); err != nil {
if strings.Contains(err.Error(), "failed to get last assistant message") {
return fmt.Errorf("session history unreadable; start a new session: %w", err)
}
return err
} Prevention
- Ensure the crush data directory is readable and has free space
- Don't downgrade across schema migrations; back up the DB first
- If the DB is corrupt, move it aside so a fresh one is created
When it happens
Trigger: GetLastAssistantMessage returns a non-ErrNoRows error: SQLite file unreadable/corrupt, table missing (failed migration), or context cancelled during the query.
Common situations: Corrupted cache DB; running with a read-only data directory; schema mismatch after downgrading crush; disk-full during query.
Related errors
- failed to create session for non-interactive mode: %w
- failed to get session: %w
- failed to save todos: %w
- error creating file history: %w
- failed to resolve session: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/489b431147fd64b0.
Report an issue: GitHub.