{"record":{"id":"1657a63a34f802a2","repo":"charmbracelet/crush","slug":"failed-to-list-messages-w-1657a6","errorCode":null,"errorMessage":"failed to list messages: %w","messagePattern":"failed to list messages: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cmd/run.go","lineNumber":549,"sourceCode":"\t\t} else if sm != nil {\n\t\t\tif err := c.UpdatePreferredModel(ctx, ws.ID, config.ScopeWorkspace, config.SelectedModelTypeSmall, *sm); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to set small model: %w\", err)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn c.UpdateAgent(ctx, ws.ID)\n}\n\n// restoreModelFromSession reads the last assistant message in the\n// session and, if it used a different provider/model than the current\n// config, updates the preferred model on the server provided the\n// provider/model is still available. This ensures that continuing a\n// session uses the same model that produced the last response.\nfunc restoreModelFromSession(ctx context.Context, c *client.Client, ws *proto.Workspace, sessionID string) error {\n\tmsgs, err := c.ListMessages(ctx, ws.ID, sessionID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to list messages: %w\", err)\n\t}\n\n\tvar lastAssistant *proto.Message\n\tfor i := len(msgs) - 1; i >= 0; i-- {\n\t\tif msgs[i].Role == proto.Assistant && !msgs[i].IsSummaryMessage {\n\t\t\tlastAssistant = &msgs[i]\n\t\t\tbreak\n\t\t}\n\t}\n\tif lastAssistant == nil || lastAssistant.Provider == \"\" || lastAssistant.Model == \"\" {\n\t\treturn nil\n\t}\n\n\tcfg := ws.Config\n\tcurrentLarge := cfg.Models[config.SelectedModelTypeLarge]\n\tif currentLarge.Provider == lastAssistant.Provider && currentLarge.Model == lastAssistant.Model {\n\t\treturn nil\n\t}","sourceCodeStart":531,"sourceCodeEnd":567,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/cmd/run.go#L531-L567","documentation":"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.","triggerScenarios":"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.","commonSituations":"Session ID no longer exists (deleted DB or wrong workspace); server unreachable; auth expired; very large session history timing out server-side.","solutions":["Verify the session ID exists in the target workspace (crush sessions list)","Check server connectivity and credentials","Inspect the wrapped cause for HTTP status details","Retry if transient","If only model restore is unwanted, run without --continue/--last"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Verify the session exists before resuming\nsessions, err := c.ListSessions(ctx, ws.ID)\nif err != nil || !containsSession(sessions, sessionID) {\n\treturn fmt.Errorf(\"session %s not found in workspace\", sessionID)\n}","typeGuard":null,"tryCatchPattern":"if err := restoreModelFromSession(ctx, c, ws, sessionID); err != nil {\n\tif strings.Contains(err.Error(), \"failed to list messages\") {\n\t\t// fall back to running without session restore, or fail loudly\n\t}\n}","preventionTips":["Verify session IDs exist before --continue/--last in scripts","Keep server connectivity stable for the resume path","Check auth before long-lived session resumes","Handle 404 by prompting for a fresh session"],"tags":["network","session","http","go"],"backgroundTag":"session-fetch-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}