{"record":{"id":"33b7cb85a583cf1b","repo":"charmbracelet/crush","slug":"failed-to-list-messages-w","errorCode":null,"errorMessage":"failed to list messages: %w","messagePattern":"failed to list messages: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/agent/agent.go","lineNumber":1692,"sourceCode":"\t\t\tToolCallID: tc.ID,\n\t\t\tOutput: fantasy.ToolResultOutputContentError{\n\t\t\t\tError: errors.New(\"tool call was interrupted and did not produce a result, you may retry this call if the result is still needed\"),\n\t\t\t},\n\t\t})\n\t}\n\tif len(syntheticParts) == 0 {\n\t\treturn fantasy.Message{}, false\n\t}\n\treturn fantasy.Message{\n\t\tRole:    fantasy.MessageRoleTool,\n\t\tContent: syntheticParts,\n\t}, true\n}\n\nfunc (a *sessionAgent) getSessionMessages(ctx context.Context, session session.Session) ([]message.Message, error) {\n\tmsgs, err := a.messages.List(ctx, session.ID)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to list messages: %w\", err)\n\t}\n\n\tif session.SummaryMessageID != \"\" {\n\t\tsummaryMsgIndex := -1\n\t\tfor i, msg := range msgs {\n\t\t\tif msg.ID == session.SummaryMessageID {\n\t\t\t\tsummaryMsgIndex = i\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif summaryMsgIndex != -1 {\n\t\t\tmsgs = msgs[summaryMsgIndex:]\n\t\t\tmsgs[0].Role = message.User\n\t\t}\n\t}\n\treturn msgs, nil\n}\n","sourceCodeStart":1674,"sourceCodeEnd":1710,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/agent/agent.go#L1674-L1710","documentation":"getSessionMessages wraps a.messages.List failures as 'failed to list messages: %w'. It is the single choke point for reading a session's message history, used by Run, Summarize and summary reconstruction (session.SummaryMessageID splicing).","triggerScenarios":"a.messages.List(ctx, session.ID) errors — store unavailable, invalid session ID, or query failure; the error propagates to 'failed to get session messages' in Run.","commonSituations":"DB corruption or lock contention on the messages table; querying messages for a session from a different/rotated database; context cancellation during large history reads.","solutions":["Verify the message store is reachable and the session ID exists in that same store","Retry on transient errors (lock timeout, cancelled context)","Check the wrapped cause: not-found means stale ID, I/O errors mean DB problems"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if _, err := sessions.Get(ctx, session.ID); err != nil {\n    return nil, fmt.Errorf(\"skip history read: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"msgs, err := getHistory(ctx, session)\nif err != nil && strings.Contains(err.Error(), \"failed to list messages\") {\n    return fallbackToEmptyHistory(), nil // degrade gracefully if product allows\n}","preventionTips":["Confirm session and message rows live in the same database instance","Add index/health checks on the messages table for large sessions","Wrap list calls with retry for transient lock errors"],"tags":["database","messages","error-wrapping"],"backgroundTag":"message-list-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}