From 89df77db6a89251f6eb061f32acc5dea9d1c36cf Mon Sep 17 00:00:00 2001 From: piyush0049 Date: Sat, 25 Jul 2026 21:03:25 +0530 Subject: [PATCH] fix(server): prevent send-on-closed-channel panic in generateTitle --- pkg/server/session_manager.go | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/pkg/server/session_manager.go b/pkg/server/session_manager.go index 7555b92a5..23774d986 100644 --- a/pkg/server/session_manager.go +++ b/pkg/server/session_manager.go @@ -891,9 +891,13 @@ func (sm *SessionManager) RunSession(ctx context.Context, sessionID, agentFilena defer cancel() defer runtimeSession.streaming.Unlock() - // Start title generation in parallel if needed + // Start title generation in parallel if needed, coordinating via WaitGroup + // so close(streamChan) does not fire while generateTitle is still sending. + var wg sync.WaitGroup if needsTitle { - go sm.generateTitle(ctx, sess, titleGen, userMessages, streamChan) + wg.Go(func() { + sm.generateTitle(ctx, sess, titleGen, userMessages, streamChan) + }) } else if titleToEmit != "" { // Re-emit the existing title so late-joining SSE consumers // and boards can pick it up without an extra API call. @@ -903,11 +907,18 @@ func (sm *SessionManager) RunSession(ctx context.Context, sessionID, agentFilena stream := runtimeSession.runtime.RunStream(streamCtx, sess) for event := range stream { if streamCtx.Err() != nil { - return + break } streamChan <- event } + // Ensure title generation finishes before defers run close(streamChan). + wg.Wait() + + if streamCtx.Err() != nil { + return + } + if err := sm.sessionStore.UpdateSession(ctx, sess); err != nil { return }