{"record":{"id":"628b6e508cf33aba","repo":"charmbracelet/crush","slug":"failed-to-send-message-w","errorCode":null,"errorMessage":"failed to send message: %w","messagePattern":"failed to send message: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cmd/run.go","lineNumber":265,"sourceCode":"\t\t\t}\n\t\t}\n\t} else {\n\t\tslog.Info(\"Created session for non-interactive run\", \"session_id\", sess.ID)\n\t}\n\n\tevents, err := c.SubscribeEvents(ctx, ws.ID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to subscribe to events: %w\", err)\n\t}\n\n\t// Mint a per-call RunID so we can correlate the terminal\n\t// RunComplete with *this* SendMessage even if the session was\n\t// busy and another turn finished first. Without it the stream\n\t// loop would exit on whichever RunComplete arrived first for\n\t// the same session and drop the queued prompt's output.\n\trunID := uuid.New().String()\n\tif err := c.SendMessage(ctx, ws.ID, sess.ID, runID, prompt); err != nil {\n\t\treturn fmt.Errorf(\"failed to send message: %w\", err)\n\t}\n\n\tstream := &runStream{\n\t\tsessionID: sess.ID,\n\t\trunID:     runID,\n\t\tout:       os.Stdout,\n\t\tread:      make(map[string]int),\n\t}\n\n\t// Start herdr integration when running inside a herdr pane.\n\thc := herdr.Init()\n\thc.SetSessionID(sess.ID)\n\tdefer hc.Close()\n\n\tdefer func() {\n\t\tif progress && stderrTTY {\n\t\t\t_, _ = fmt.Fprintf(os.Stderr, ansi.ResetProgressBar)\n\t\t}","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/cmd/run.go#L247-L283","documentation":"Wraps errors from c.SendMessage(), which submits the user prompt to the agent for the session. Thrown when the message cannot be enqueued/dispatched to the session agent.","triggerScenarios":"`crush run` calls c.SendMessage(ctx, ws.ID, sess.ID, runID, prompt) and it returns an error — agent for the session isn't running, session state is invalid, or provider call setup fails immediately.","commonSituations":"Session was resolved but its agent was torn down; empty prompt; provider credentials rejected at request time; the session is in a corrupted state after a crashed run.","solutions":["Verify the agent is ready (the run already waits via waitForAgent) and re-run","Test provider credentials with `crush` interactive mode","Start a fresh session (drop --continue) if the old session state is suspect","Inspect verbose logs for the wrapped SendMessage cause"],"exampleFix":"// before: empty prompt when arg parsing failed\nprompt := flag.Arg(0) // \"\"\nc.SendMessage(ctx, ws.ID, sess.ID, runID, prompt)\n// after\nif prompt == \"\" {\n\treturn fmt.Errorf(\"prompt is required\")\n}\nif err := c.SendMessage(ctx, ws.ID, sess.ID, runID, prompt); err != nil {\n\treturn fmt.Errorf(\"failed to send message: %w\", err)\n}","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(prompt) == \"\" {\n\treturn fmt.Errorf(\"prompt is required\")\n}\nif sess == nil || sess.ID == \"\" {\n\treturn fmt.Errorf(\"no active session; cannot send message\")\n}","typeGuard":null,"tryCatchPattern":"if err := c.SendMessage(ctx, ws.ID, sess.ID, runID, prompt); err != nil {\n\tif errors.Is(err, context.Canceled) {\n\t\treturn err\n\t}\n\treturn fmt.Errorf(\"failed to send message: %w\", err)\n}","preventionTips":["Always validate the prompt is non-empty before sending","Ensure waitForAgent succeeded before SendMessage","Use a fresh runID (uuid) for every SendMessage as the code does","Recreate the session if SendMessage fails repeatedly (state may be corrupt)"],"tags":["go","agent","message","lifecycle"],"backgroundTag":"send-message-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}