Repository navigation
fix(session/database): maintain UpdateTime on app/user state writes - #1204
Merged
Merged
Conversation
storageAppState / storageUserState were saved without ever assigning UpdateTime, so Go's zero time.Time was written explicitly. MySQL rejects that under its default strict mode (NO_ZERO_DATE / STRICT_TRANS_TABLES): failed to save app state: Error 1292 (22007): Incorrect datetime value: '0000-00-00' for column 'update_time' at row 1 SQLite, PostgreSQL and Spanner accept the zero value, so only MySQL failed whenever app:/user: scoped state was persisted (on Create or via an event's state delta). A DDL default can't fix it: the column is present in the generated statement, so the explicit zero value always wins. Assign UpdateTime before saving both state tables, mirroring how storageSession.UpdateTime is already maintained: createdSession.UpdateTime on Create and event.Timestamp on AppendEvent. Setting it explicitly (rather than a GORM autoUpdateTime tag) keeps the platform.Now time provider seam intact for deterministic tests. Fixes google#1177
wolo-lab
approved these changes
Aug 27, 2026
This was referenced Aug 27, 2026
wolo-lab
added a commit
that referenced
this pull request
Sep 4, 2026
…d in this backport The #1204 cherry-pick added TestDatabaseService_StateUpdateTimeIsSet, and the #1237 cherry-pick two commits later dropped it while re-anchoring the test file around the workflow-event test that does not exist on this line. That left the #1204 fix shipping with no coverage: with all four UpdateTime assignments removed from service.go, the whole session tree stayed green. Restored verbatim from main, so the two branches carry the same test.
jjsasha63
pushed a commit
that referenced
this pull request
Sep 4, 2026
* fix(session/vertexai): treat nil function args as an empty struct (#1322) toStructPB marshals its input to JSON and hands the result to structpb.Struct.UnmarshalJSON. A nil map marshals to the literal null, which structpb rejects, so toStructPB returns an error where the structpb.NewStruct call it replaced returned an empty Struct. createAiplatformpbContent calls toStructPB unconditionally for FunctionCall.Args and FunctionResponse.Response, unlike the other call sites which are guarded by a length check. A tool that declares no parameters produces a FunctionCall with nil Args, so the conversion fails, AppendEvent returns an error and the event is never persisted. The same applies to a tool that returns no payload. Treat a null marshaling as an empty Struct, restoring the previous behaviour for every caller. Fixes #1321 (cherry picked from commit c88d496) * fix(session/database): maintain UpdateTime on app/user state writes (#1204) storageAppState / storageUserState were saved without ever assigning UpdateTime, so Go's zero time.Time was written explicitly. MySQL rejects that under its default strict mode (NO_ZERO_DATE / STRICT_TRANS_TABLES): failed to save app state: Error 1292 (22007): Incorrect datetime value: '0000-00-00' for column 'update_time' at row 1 SQLite, PostgreSQL and Spanner accept the zero value, so only MySQL failed whenever app:/user: scoped state was persisted (on Create or via an event's state delta). A DDL default can't fix it: the column is present in the generated statement, so the explicit zero value always wins. Assign UpdateTime before saving both state tables, mirroring how storageSession.UpdateTime is already maintained: createdSession.UpdateTime on Create and event.Timestamp on AppendEvent. Setting it explicitly (rather than a GORM autoUpdateTime tag) keeps the platform.Now time provider seam intact for deterministic tests. Fixes #1177 Co-authored-by: wolo <[email protected]> (cherry picked from commit 245ba28) * fix(session/database): format stale-session timestamps as UnixMicro (#1237) The stale-session error compared UnixMicro() values (microseconds since epoch) but formatted them with time.Unix(0, x), whose second argument is nanoseconds. Being off by 1000x, every real timestamp collapsed to 1970-01-2x, so operators debugging optimistic-concurrency rejections saw: stale session error: last update time from request (1970-01-21T15:38:42.372056389Z) is older than in database (1970-01-21T15:38:42.372500103Z) instead of the actual wall-clock times. The comparison itself is unaffected (both sides share the same unit); only the display strings were wrong. Use time.UnixMicro, which interprets the value as microseconds. Adds a regression test that triggers the stale path via an optimistic-concurrency conflict and asserts the rendered timestamps are the real times, not 1970. Fixes #1170 Co-authored-by: wolo <[email protected]> (cherry picked from commit 3f69c50) * fix(session/vertexai): quote userId in AIP-160 list filter (#1171) listSessions built the Vertex AI Agent Engine list filter by interpolating the raw UserID into a quoted AIP-160 string literal (fmt.Sprintf("userId=\"%s\"", req.UserID)). A double quote in UserID breaks out of the literal and appends attacker-controlled predicates, e.g. UserID `attacker" OR userId!="` yields the filter `userId="attacker" OR userId!=""`, which returns sessions for every user of the deployment (cross-user session enumeration). Add quoteFilterLiteral, which escapes backslashes then double quotes so the value stays inside the literal, and use it when building the filter. Adds a regression test covering quote injection, backslash-only, and empty input. This is the Go counterpart of the same issue previously fixed in adk-python (google/adk-python#5270, PR google/adk-python#5273, commit bdece00). Co-authored-by: wolo <[email protected]> (cherry picked from commit 78b8355) * test(session/database): restore the UpdateTime regression test dropped in this backport The #1204 cherry-pick added TestDatabaseService_StateUpdateTimeIsSet, and the #1237 cherry-pick two commits later dropped it while re-anchoring the test file around the workflow-event test that does not exist on this line. That left the #1204 fix shipping with no coverage: with all four UpdateTime assignments removed from service.go, the whole session tree stayed green. Restored verbatim from main, so the two branches carry the same test.
kdroste-google
pushed a commit
to kdroste-google/adk-go
that referenced
this pull request
Sep 29, 2026
…oogle#1204) storageAppState / storageUserState were saved without ever assigning UpdateTime, so Go's zero time.Time was written explicitly. MySQL rejects that under its default strict mode (NO_ZERO_DATE / STRICT_TRANS_TABLES): failed to save app state: Error 1292 (22007): Incorrect datetime value: '0000-00-00' for column 'update_time' at row 1 SQLite, PostgreSQL and Spanner accept the zero value, so only MySQL failed whenever app:/user: scoped state was persisted (on Create or via an event's state delta). A DDL default can't fix it: the column is present in the generated statement, so the explicit zero value always wins. Assign UpdateTime before saving both state tables, mirroring how storageSession.UpdateTime is already maintained: createdSession.UpdateTime on Create and event.Timestamp on AppendEvent. Setting it explicitly (rather than a GORM autoUpdateTime tag) keeps the platform.Now time provider seam intact for deterministic tests. Fixes google#1177 Co-authored-by: wolo <[email protected]>
li-xuankun312
added a commit
to li-xuankun312/einsteinOS
that referenced
this pull request
Sep 29, 2026
…oogle#1204) storageAppState / storageUserState were saved without ever assigning UpdateTime, so Go's zero time.Time was written explicitly. MySQL rejects that under its default strict mode (NO_ZERO_DATE / STRICT_TRANS_TABLES): failed to save app state: Error 1292 (22007): Incorrect datetime value: '0000-00-00' for column 'update_time' at row 1 SQLite, PostgreSQL and Spanner accept the zero value, so only MySQL failed whenever app:/user: scoped state was persisted (on Create or via an event's state delta). A DDL default can't fix it: the column is present in the generated statement, so the explicit zero value always wins. Assign UpdateTime before saving both state tables, mirroring how storageSession.UpdateTime is already maintained: createdSession.UpdateTime on Create and event.Timestamp on AppendEvent. Setting it explicitly (rather than a GORM autoUpdateTime tag) keeps the platform.Now time provider seam intact for deterministic tests. Fixes google#1177 Co-authored-by: wolo <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #1177.
storageAppState/storageUserState(session/database) were saved without ever assigningUpdateTime, so Go's zerotime.Timewas written explicitly. MySQL rejects that under its default strict mode (NO_ZERO_DATE/STRICT_TRANS_TABLES):SQLite, PostgreSQL and Spanner accept the zero value, so only MySQL failed — whenever
app:/user:scoped state was persisted (onCreate, or via an event's state delta inAppendEvent). A DDL-levelDEFAULT CURRENT_TIMESTAMPcan't fix it: the column is present in the generated statement, so the explicit (invalid) zero value always wins.Change
Assign
UpdateTimebefore saving both state tables, mirroring howstorageSession.UpdateTimeis already maintained:Create→createdSession.UpdateTime(so app/user/session share one create timestamp)AppendEvent/applyEvent→event.Timestamp(matching the adjacentstorageSess.UpdateTime = event.Timestamp)I set it explicitly rather than adding a GORM
autoUpdateTimetag on purpose:autoUpdateTimecallstime.Now()internally and would bypass the repo'splatform.Now(ctx)seam that makes time deterministic in tests (e.g.Test_databaseService_CreateUsesProviders).Testing Plan
TestDatabaseService_StateUpdateTimeIsSet: creates a session withapp:/user:scoped state and appends an event carryingapp:/user:deltas, then reads theapp_states/user_statesrows back and assertsUpdateTimeis populated (non-zero) on both theCreateandAppendEventpaths.update_time— is gone. (White-box: the test is inpackage databaseand queries the storage tables via the unexported handle.)go test -race -count=1 ./session/database/— pass (full package)go build -mod=readonly ./...— passgo vet ./session/database/— passgolangci-lint run ./session/database/— 0 issuesgofmt -l— clean