Skip to content

AutoCreateSession should only create on NotFound, not on all Get errors #751

@tiagostutz

Description

@tiagostutz

Summary

When runner.Config.AutoCreateSession is true, the runner calls sessionService.Get() and falls back to sessionService.Create() on any error — not just when the session doesn't exist. This can silently create a new session on transient database errors (timeouts, connection failures), which is unsafe for multi-turn conversational agents that depend on session history.

Current Behavior

In runner.go lines 142-161:

getResp, err := r.sessionService.Get(ctx, &session.GetRequest{...})
if err != nil {
    if !r.autoCreateSession {
        yield(nil, err)
        return
    }
    // Creates on ANY error, not just NotFound
    createResp, err := r.sessionService.Create(ctx, &session.CreateRequest{...})
    ...
}

All Get errors are treated the same — the runner does not distinguish between:

  • NotFound (session never existed → safe to create)
  • Transient errors (database timeout, connection refused → should fail fast)

Problem

For multi-turn conversational agents, this behavior can silently drop conversation history:

  1. User has an ongoing conversation with session abc-123
  2. Database has a brief connectivity blip
  3. sessionService.Get("abc-123") returns a transient error
  4. Runner creates a new empty session with ID abc-123 instead of surfacing the error
  5. User's conversation history is silently lost

This forces multi-turn agents to implement their own get-or-create pattern with explicit error type checking rather than using AutoCreateSession.

Expected Behavior

When AutoCreateSession is true, the runner should only call Create when the Get error indicates the session does not exist (e.g., codes.NotFound). Transient errors should be propagated to the caller.

Suggested Fix

getResp, err := r.sessionService.Get(ctx, &session.GetRequest{...})
if err != nil {
    if !r.autoCreateSession || !isNotFoundError(err) {
        yield(nil, err)
        return
    }
    createResp, err := r.sessionService.Create(ctx, &session.CreateRequest{...})
    ...
}

Where isNotFoundError checks for gRPC codes.NotFound and/or the string-based "not found" pattern used by the database session service (which wraps gorm.ErrRecordNotFound as "database error while fetching session: record not found").

Workaround

We currently implement manual get-or-create logic in our service layer for multi-turn agents, bypassing AutoCreateSession entirely.

Environment

  • google.golang.org/adk v1.1.0
  • Go 1.24

Metadata

Metadata

Labels

bugSomething isn't working

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions