Skip to content

Conversation

@fhuzjan
Copy link

@fhuzjan fhuzjan commented Nov 20, 2025

fix: Use model_validate instead of model_copy for EventActions deserialization

Fixes #3633

Problem

When using DatabaseSessionService, nested Pydantic models in EventActions
(specifically EventCompaction) were incorrectly deserialized as dictionaries
instead of proper Pydantic model instances. This caused AttributeError when
trying to access attributes on the compaction object.

Root Cause

In database_session_service.py line 364, the code used:
EventActions().model_copy(update=self.actions.model_dump())

Pydantic's model_copy() does not validate or reconstruct nested Pydantic
models - it just assigns dictionary values directly. This meant that nested
objects like EventCompaction remained as dicts after deserialization.

Solution

Changed line 364 to use model_validate() instead:
EventActions.model_validate(self.actions.model_dump()) if self.actions else None

model_validate() properly reconstructs nested Pydantic models from
dictionaries, ensuring EventCompaction and other nested models are
instantiated correctly.

Testing

Added comprehensive test test_event_compaction_deserialization that:

  • Creates an event with EventCompaction
  • Persists it to database
  • Retrieves it and verifies compaction is an EventCompaction instance
  • Tests with all three session service types (InMemory, Database, SQLite)

All 45 session service tests pass, including the new test.

Impact

  • Fixes EventCompaction deserialization bug in DatabaseSessionService
  • Also fixes the same issue in SqliteSessionService
  • No impact on InMemorySessionService (it stores objects directly)
  • Prevents AttributeError in ADK's own code (contents.py:265, compaction.py:117)

…alization

Fixes google#3633

## Problem
When using DatabaseSessionService, nested Pydantic models in EventActions
(specifically EventCompaction) were incorrectly deserialized as dictionaries
instead of proper Pydantic model instances. This caused AttributeError when
trying to access attributes on the compaction object.

## Root Cause
In database_session_service.py line 364, the code used:
  EventActions().model_copy(update=self.actions.model_dump())

Pydantic's model_copy() does not validate or reconstruct nested Pydantic
models - it just assigns dictionary values directly. This meant that nested
objects like EventCompaction remained as dicts after deserialization.

## Solution
Changed line 364 to use model_validate() instead:
  EventActions.model_validate(self.actions.model_dump()) if self.actions else None

model_validate() properly reconstructs nested Pydantic models from
dictionaries, ensuring EventCompaction and other nested models are
instantiated correctly.

## Testing
Added comprehensive test test_event_compaction_deserialization that:
- Creates an event with EventCompaction
- Persists it to database
- Retrieves it and verifies compaction is an EventCompaction instance
- Tests with all three session service types (InMemory, Database, SQLite)

All 45 session service tests pass, including the new test.

## Impact
- Fixes EventCompaction deserialization bug in DatabaseSessionService
- Also fixes the same issue in SqliteSessionService
- No impact on InMemorySessionService (it stores objects directly)
- Prevents AttributeError in ADK's own code (contents.py:265, compaction.py:117)
@google-cla
Copy link

google-cla bot commented Nov 20, 2025

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @fhuzjan, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves a critical deserialization bug where nested Pydantic models within EventActions were being treated as plain dictionaries instead of proper Pydantic instances, leading to runtime errors. The fix involves switching from model_copy() to model_validate() during the deserialization process, ensuring that all nested models are correctly reconstructed. A new, thorough test case has been added to validate this behavior across all relevant session service types.

Highlights

  • Fixes Pydantic Deserialization Issue: Addresses a bug where nested Pydantic models within EventActions (specifically EventCompaction) were incorrectly deserialized as plain dictionaries instead of proper Pydantic instances when using DatabaseSessionService and SqliteSessionService.
  • Root Cause Identified: The problem stemmed from using EventActions().model_copy(update=self.actions.model_dump()), which does not validate or reconstruct nested Pydantic models from dictionary representations.
  • Solution Implemented: The model_copy() call has been replaced with EventActions.model_validate(self.actions.model_dump()) to ensure that nested Pydantic models are properly reconstructed and validated during deserialization.
  • Comprehensive Testing Added: A new test, test_event_compaction_deserialization, has been introduced to verify the correct deserialization of EventCompaction across InMemory, Database, and SQLite session services. All 45 session service tests, including the new one, are passing.
  • Impact on Services: This fix resolves AttributeErrors in DatabaseSessionService and SqliteSessionService related to accessing attributes on incorrectly deserialized nested models. InMemorySessionService is unaffected as it stores objects directly.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@adk-bot
Copy link
Collaborator

adk-bot commented Nov 20, 2025

Response from ADK Triaging Agent

Hello @fhuzjan, thank you for creating this PR!

It looks like you have not signed the Contributor License Agreement (CLA). Please visit https://cla.developers.google.com/ to sign it.

This is a necessary step before we can review your contribution. Thanks!

@adk-bot adk-bot added the services [Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc label Nov 20, 2025
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This is a great pull request that clearly addresses a deserialization bug with nested Pydantic models. The problem, root cause, and solution are well-documented in the description. The fix to use model_validate instead of model_copy is correct and effectively resolves the issue. The addition of the test_event_compaction_deserialization test is excellent, as it provides comprehensive coverage for the fix across all session service types. I have one minor suggestion to improve the code formatting for better readability.

Comment on lines +365 to +367
actions=EventActions.model_validate(self.actions.model_dump())
if self.actions
else None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For better readability and conciseness, this conditional expression can be formatted as a standard one-line ternary operator.

        actions=EventActions.model_validate(self.actions.model_dump()) if self.actions else None,

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Script autoformat.sh rewrites this into multiple lines

@ryanaiagent ryanaiagent self-assigned this Nov 21, 2025
@ryanaiagent
Copy link
Collaborator

Hi @fhuzjan , Thank you for your contribution! We appreciate you taking the time to submit this pull request.
Can you please the lint error before we proceed with the review. You can fix by using autoformat.sh

@fhuzjan
Copy link
Author

fhuzjan commented Nov 21, 2025

Hi @fhuzjan , Thank you for your contribution! We appreciate you taking the time to submit this pull request. Can you please the lint error before we proceed with the review. You can fix by using autoformat.sh

@ryanaiagent thank you for the reply, I have made and pushed the changes using autoformat.sh

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

services [Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

EventCompaction deserialized as dict instead of Pydantic model in DatabaseSessionService

3 participants