{"record":{"id":"4c690b8aa1c65593","repo":"charmbracelet/crush","slug":"failed-to-get-session-w","errorCode":null,"errorMessage":"failed to get session: %w","messagePattern":"failed to get session: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/agent/agent.go","lineNumber":695,"sourceCode":"\t\tsystemPrompt += \"\\n\\n<mcp-instructions>\\n\" + s + \"\\n</mcp-instructions>\"\n\t}\n\n\tif len(agentTools) > 0 {\n\t\t// Add Anthropic caching to the last tool.\n\t\tagentTools[len(agentTools)-1].SetProviderOptions(a.getCacheControlOptions())\n\t}\n\n\tagent := fantasy.NewAgent(\n\t\tlargeModel.Model,\n\t\tfantasy.WithSystemPrompt(systemPrompt),\n\t\tfantasy.WithTools(agentTools...),\n\t\tfantasy.WithUserAgent(userAgent),\n\t)\n\n\tsessionLock := sync.Mutex{}\n\tcurrentSession, err := a.sessions.Get(ctx, call.SessionID)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get session: %w\", err)\n\t}\n\n\tmsgs, err := a.getSessionMessages(ctx, currentSession)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get session messages: %w\", err)\n\t}\n\n\t// Generate title from the first real (non-shell) user prompt.\n\t// can take tens of seconds. Blocking Run on it delays the\n\t// response to the caller. Use a detached context so the title\n\t// goroutine survives Run's cancel.\n\tif !hasUserTextMessage(msgs) {\n\t\ttitleCtx := context.WithoutCancel(ctx)\n\t\tgo a.GenerateTitle(titleCtx, call.SessionID, call.Prompt)\n\t}\n\n\t// Add the user message to the session.\n\t_, err = a.createUserMessage(ctx, call)","sourceCodeStart":677,"sourceCodeEnd":713,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/agent/agent.go#L677-L713","documentation":"Run wraps failures from the session store lookup with 'failed to get session: %w'. The agent could not load the session identified by call.SessionID before building the prompt, so the run aborts with the underlying store error attached.","triggerScenarios":"a.sessions.Get(ctx, call.SessionID) fails inside Run (or Summarize via Run) — session ID does not exist, DB error, or the context is cancelled mid-query.","commonSituations":"Caller passes a stale or deleted session ID; SQLite file locked/corrupt; request context cancelled while the query runs; session created in another DB instance.","solutions":["Verify the SessionID passed in the call exists (sessions.Get or session list) before running","Check DB health (file path, permissions, locks) if IDs are valid","Inspect the wrapped %w error to distinguish not-found vs storage failure"],"exampleFix":"// before\nout, err := agent.Run(ctx, agent.Call{SessionID: id})\n// after\nif _, err := sessions.Get(ctx, id); err != nil {\n    return fmt.Errorf(\"session %s unavailable: %w\", id, err)\n}\nout, err := agent.Run(ctx, agent.Call{SessionID: id})","handlingStrategy":"validation","validationCode":"if _, err := sessions.Get(ctx, call.SessionID); err != nil {\n    return fmt.Errorf(\"cannot run: session %s missing: %w\", call.SessionID, err)\n}","typeGuard":null,"tryCatchPattern":"out, err := agent.Run(ctx, call)\nif err != nil && strings.HasPrefix(err.Error(), \"failed to get session\") {\n    // inspect errors.Unwrap for not-found vs db failure\n}","preventionTips":["Validate SessionID exists before invoking Run or Summarize","Avoid deleting sessions while runs are in flight","Keep request contexts alive long enough for the initial DB reads"],"tags":["database","session","error-wrapping"],"backgroundTag":"session-not-found","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}