chenhg5/cc-connect · error
session is closed
Error message
session is closed
What it means
antigravitySession.Send checks the atomic 'alive' flag and refuses to submit a prompt once the session has been closed or the underlying process has exited. It is a lifecycle guard against using a dead session handle.
Source
Thrown at agent/antigravity/session.go:77
if mode == "default" {
bridge, err := newAgyPermissionBridge(sessionCtx, as.events)
if err != nil {
cancel()
return nil, fmt.Errorf("antigravity: initialize permission bridge: %w", err)
}
as.permissionBridge = bridge
}
if resumeID != "" && resumeID != core.ContinueSession {
as.chatID.Store(resumeID)
}
return as, nil
}
func (as *antigravitySession) Send(prompt string, messageID string, images []core.ImageAttachment, files []core.FileAttachment) error {
if !as.alive.Load() {
return fmt.Errorf("session is closed")
}
// Capture existing chat logs so we can identify a new session on first turn
preEntries := make(map[string]bool)
homeDir, err := os.UserHomeDir()
if err == nil {
slug := antigravityProjectSlug(as.workDir)
chatsDir := filepath.Join(homeDir, ".gemini", "tmp", slug, "chats")
if entries, err := os.ReadDir(chatsDir); err == nil {
for _, entry := range entries {
if !entry.IsDir() && strings.HasSuffix(entry.Name(), ".jsonl") {
preEntries[entry.Name()] = true
}
}
}
}
// Save images and files into the workspaceView on GitHub (pinned to 4000b2338a)
Solutions
- Start a fresh session via StartSession instead of reusing the closed one.
- Check session liveness (if exposed) before Send, or recreate the session on this error.
- In platform handlers, catch this error and fall back to creating a new session for the user's next message.
- Investigate why the session died earlier (check the error event stream / agy stderr).
Example fix
// before
err := cachedSession.Send(prompt, id, nil, nil)
// after
if err := cachedSession.Send(prompt, id, nil, nil); err != nil && err.Error() == "session is closed" {
cachedSession, err = agent.StartSession(ctx, opts)
err = cachedSession.Send(prompt, id, nil, nil)
} Defensive patterns
Strategy: try-catch
Try / catch
if err := session.Send(prompt, id, nil, nil); err != nil {
if err.Error() == "session is closed" {
session, err = agent.StartSession(ctx, opts)
if err == nil { err = session.Send(prompt, id, nil, nil) }
}
} Prevention
- Evict dead sessions from your session cache on terminal events.
- Recreate the session automatically when agy exits unexpectedly.
- Stop routing platform messages to a session after /stop.
When it happens
Trigger: Calling Send on a session after Stop()/Close(), after the agy process exited, or after an event-stream terminal event marked the session dead.
Common situations: The engine's session cache retaining an expired session; agy crashing mid-session and the caller retrying Send on the same handle; messages arriving from the platform after the user ran /stop.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- listen for Agy permission hooks: %w
- generate permission bridge token: %w
- resolve home directory for Agy permission bridge: %w
- create Agy permission overlay: %w
- parse existing Agy hooks %s: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/a6b748528786dbb3.
Report an issue: GitHub.