charmbracelet/crush · error

failed to list messages: %w

Error message

failed to list messages: %w

What it means

restoreModelFromSession (internal/cmd/run.go:549) wraps errors from c.ListMessages when resuming a session (--continue/--last). It needs the last assistant message to restore the previously used model; failing to fetch message history aborts the model-restore step.

Source

Thrown at internal/cmd/run.go:549

		} else if sm != nil {
			if err := c.UpdatePreferredModel(ctx, ws.ID, config.ScopeWorkspace, config.SelectedModelTypeSmall, *sm); err != nil {
				return fmt.Errorf("failed to set small model: %w", err)
			}
		}
	}

	return c.UpdateAgent(ctx, ws.ID)
}

// restoreModelFromSession reads the last assistant message in the
// session and, if it used a different provider/model than the current
// config, updates the preferred model on the server provided the
// provider/model is still available. This ensures that continuing a
// session uses the same model that produced the last response.
func restoreModelFromSession(ctx context.Context, c *client.Client, ws *proto.Workspace, sessionID string) error {
	msgs, err := c.ListMessages(ctx, ws.ID, sessionID)
	if err != nil {
		return fmt.Errorf("failed to list messages: %w", err)
	}

	var lastAssistant *proto.Message
	for i := len(msgs) - 1; i >= 0; i-- {
		if msgs[i].Role == proto.Assistant && !msgs[i].IsSummaryMessage {
			lastAssistant = &msgs[i]
			break
		}
	}
	if lastAssistant == nil || lastAssistant.Provider == "" || lastAssistant.Model == "" {
		return nil
	}

	cfg := ws.Config
	currentLarge := cfg.Models[config.SelectedModelTypeLarge]
	if currentLarge.Provider == lastAssistant.Provider && currentLarge.Model == lastAssistant.Model {
		return nil
	}

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Verify the session ID exists in the target workspace (crush sessions list)
  2. Check server connectivity and credentials
  3. Inspect the wrapped cause for HTTP status details
  4. Retry if transient
  5. If only model restore is unwanted, run without --continue/--last
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify the session exists before resuming
sessions, err := c.ListSessions(ctx, ws.ID)
if err != nil || !containsSession(sessions, sessionID) {
	return fmt.Errorf("session %s not found in workspace", sessionID)
}

Try / catch

if err := restoreModelFromSession(ctx, c, ws, sessionID); err != nil {
	if strings.Contains(err.Error(), "failed to list messages") {
		// fall back to running without session restore, or fail loudly
	}
}

Prevention

When it happens

Trigger: runNonInteractive resolves a session to continue and calls c.ListMessages(ctx, ws.ID, sessionID), which fails due to network error, HTTP 401/404/500, or canceled context.

Common situations: Session ID no longer exists (deleted DB or wrong workspace); server unreachable; auth expired; very large session history timing out server-side.

Related errors


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