Repository navigation
adk_request_credential FunctionCall args contain non-JSON-serializable SecuritySchemeType enum #6006
Description
🔴 Required Information
Describe the Bug:
build_auth_request_event in src/google/adk/flows/llm_flows/functions.py builds the adk_request_credential (EUC) FunctionCall.args with AuthToolArguments(...).model_dump(exclude_none=True, by_alias=True). The default mode="python" leaves the auth scheme's type field as a live SecuritySchemeType enum member inside the args dict, rather than its string value. The resulting Event.content is therefore not JSON-serializable: any consumer that calls json.dumps on the in-memory event content raises TypeError: Object of type SecuritySchemeType is not JSON serializable.
This is latent for most flows because the session DB launders enums to strings on write (pydantic JSON serialization), and ADK's own auth preprocessor re-validates the args from either form. It surfaces for any consumer that serializes the in-memory event before it round-trips through the DB. A concrete trigger is memory ingestion: VertexAiMemoryBankService hands the in-memory event.content to the Vertex SDK, which json.dumps's it.
Steps to Reproduce:
Run the snippet below against google-adk 2.2.0. It performs the same model_dump call as build_auth_request_event and then the same json.dumps the Vertex SDK performs during memory ingestion.
import json
from google.adk.auth.auth_tool import AuthConfig, AuthToolArguments
from google.adk.auth.auth_credential import AuthCredential, AuthCredentialTypes, OAuth2Auth
from google.adk.auth.auth_schemes import OAuth2
from fastapi.openapi.models import OAuthFlows, OAuthFlowAuthorizationCode
scheme = OAuth2(flows=OAuthFlows(authorizationCode=OAuthFlowAuthorizationCode(
authorizationUrl="https://example/authorize", tokenUrl="https://example/token", scopes={})))
cfg = AuthConfig(auth_scheme=scheme,
raw_auth_credential=AuthCredential(auth_type=AuthCredentialTypes.OAUTH2,
oauth2=OAuth2Auth(client_id="x", client_secret="y")))
# The exact dump build_auth_request_event performs (functions.py, default mode="python")
args = AuthToolArguments(function_call_id="abc", auth_config=cfg).model_dump(
exclude_none=True, by_alias=True)
print(repr(args["authConfig"]["authScheme"]["type"])) # <SecuritySchemeType.oauth2: 'oauth2'> — live enum
json.dumps(args) # TypeError: Object of type SecuritySchemeType is not JSON serializable
# The fix: mode="json" coerces the enum to its string value, same dump otherwise
fixed = AuthToolArguments(function_call_id="abc", auth_config=cfg).model_dump(
mode="json", exclude_none=True, by_alias=True)
print(repr(fixed["authConfig"]["authScheme"]["type"])) # 'oauth2'
json.dumps(fixed) # passesExpected Behavior:
The adk_request_credential FunctionCall.args are JSON-serializable, consistent with how the same content is stored and re-read from the session DB. model_dump(mode="json", exclude_none=True, by_alias=True) coerces the enum to its "oauth2" string while preserving aliases; ADK's parse-back is unaffected because pydantic validation accepts the string form (exactly what it already does for DB-read events).
Observed Behavior:
json.dumps on the in-memory event content raises:
TypeError: Object of type SecuritySchemeType is not JSON serializable
In a real flow (memory ingest on the EUC turn) this surfaces as a background task failure:
ERROR vertex_ai_memory_bank_service.py | Background ingest_events task failed: Object of type SecuritySchemeType is not JSON serializable
Environment Details:
- ADK Library Version (pip show google-adk): 2.2.0 (latest release; identical on
main, the dump is atfunctions.py:305, SHA9670ce2) - Desktop OS: macOS
- Python Version (python -V): 3.13
Model Information:
- Are you using LiteLLM: No
- Which model is being used: N/A, the bug is in event construction and model-independent
🟡 Optional Information
Regression:
Not a recent regression. The python-mode dump has been in place across releases (present in the 1.x line and unchanged on the current 2.x main); it only becomes observable when a consumer serializes the in-memory EUC event before DB round-trip.
Logs:
TypeError: Object of type SecuritySchemeType is not JSON serializable
Additional Context:
Sibling call sites in the same file use the same python-mode model_dump and may carry the same hazard if their models contain enums (like the tool-confirmation args around functions.py:368/:371, and event.actions.model_dump(...) near line 1241). Worth a glance during the fix, but the auth-request path is the confirmed, reproducible one. Discovered downstream while validating an OAuth resume flow; the in-memory event reached json.dumps via memory ingestion before any DB round-trip.
Minimal Reproduction Code:
Inline in Steps to Reproduce above; self-contained against a clean pip install google-adk==2.2.0.
How often has this issue occurred?:
- Always (100%), deterministic for any consumer that
json.dumps's the in-memory EUC event content.
Activity
adk-bot commentedon Jun 7, 2026
GitHub Issue #6006 Analysis: adk_request_credential FunctionCall args contain non-JSON-serializable SecuritySchemeType enum
Executive Summary
.model_dump()serialization usesmode="python", retaining nestedSecuritySchemeTypeenums as live PythonEnumobjects in the dumped args dictionary, rather than serializing them to primitive strings. When downstream consumers (such as the Vertex AI SDK during memory ingestion) attempt to serialize these in-memory events via standard JSON methods (likejson.dumps()), it raises aTypeError: Object of type SecuritySchemeType is not JSON serializableexception.VertexAiMemoryBankService) whenever an EUC turn auth-request occurs, blocking critical functionality. The fix is low risk and simply requires updating.model_dump()to usemode="json".Detailed Analysis
1. Root Cause Analysis ("What is broken?")
When an End User Credential (EUC) request is built to execute tools or toolset-level authentication,
build_auth_request_event(...)is invoked to construct an authorization request with anadk_request_credentialFunctionCall. Inside this function, theAuthToolArgumentspydantic model is serialized to a dictionary via:Because no Python-to-JSON serialization mode is specified, Pydantic defaults to
mode="python". This preserves the nestedSecuritySchemeTypeenum fields (the auth scheme'stypefield, such asSecuritySchemeType.oauth2) as live PythonEnummembers nested inside the returned dictionary.While the issue is usually hidden during round-tripping through standard databases (which deserialize JSON to string values, automatically "cleansing" the enum objects), it immediately surfaces when any consumer or SDK performs standard JSON serialization (such. as
json.dumps) directly on the in-memory event content beforehand.A critical downstream failure occurs inside the
VertexAiMemoryBankServicebackground taskingest_eventswhere the intact in-memoryevent.contentcontaining the liveSecuritySchemeTypeobject is passed to the Vertex SDK, raising:TypeError: Object of type SecuritySchemeType is not JSON serializableCode References
The failure resides in the following two core locations where
AuthToolArgumentsare dumped withoutmode="json":Additionally, other sibling call sites of
.model_dumpare vulnerable to the same issue if they ever process nestedEnummembers:originalFunctionCallandtoolConfirmationto construct tool confirmation requests.2. Existing Pull Requests ("Is there a linked PR that fixes this issue?")
gh pr list --repo google/adk-python --search "6006"returned no matches. However, the root cause logic has been verified locally on the currentmainbranch.3. Recommendation
mode="json"natively coerces nested enums into their target JSON strings while remaining fully backward-compatible with ADK's internal parsers (which safely validate enum strings back to enum members).Next Steps & Summary of Work
I analyzed GitHub Issue #6006, mapped down all root extraction failure points including functions.py and external workflow counterparts, verified that no linked PRs currently exist, and provided a comprehensive architectural fix.
Please let me know if you would like me to proceed with implementing the fixes and verifying the tests!
surajksharma07 commentedon Jun 8, 2026
@doughayden As a quick workaround, try swapping the .model_dump() at functions.py:305 (and the matching call in _workflow_hitl_utils.py) to use mode="json" — i.e. .model_dump(mode="json", exclude_none=True, by_alias=True) — and verify that json.dumps(args) no longer raises in your OAuth EUC flow.
If this resolves the memory ingestion crash on your end, please run the full test suite and confirm everything passes before pushing the PR — want to make sure the parse-back path (enum string → enum member via Pydantic validation) holds up end-to-end.
Happy to take a look once you've confirmed it's solid!
fix: JSON-mode EUC dump on workflow HITL path
doughayden commentedon Jun 8, 2026
@surajksharma07 thanks for the workaround confirmation. I opened #6007 a day ago with exactly that
mode="json"fix, and following your note I've expanded it to the second call site:create_auth_request_eventinworkflow/utils/_workflow_hitl_utils.py, the v2 workflow HITL path. Both auth-request builders now dump withmode="json", each with a regression test.On the memory ingestion crash: confirmed resolved on our end. We originally hit this exact failure through
VertexAiMemoryBankServiceingest (Object of type SecuritySchemeType is not JSON serializable). Re-running our OAuth EUC flow today with themode="json"fix in place, the post-resume ingest completed clean: no serialization error and zero errors in the log window. In our deployment the in-memory event that ingest serializes comes from our own resume-message builder, so that's where we observe the real-world fix, but it's the identical bug pattern this PR clears in ADK's builders. I verified the PR's exact change against currentmainwith the inlinejson.dumpsrepro from the issue.Full unit suite is green locally, including the two new regression tests (each fails before its change, passes after). PR is ready for review whenever you have a chance.
surajksharma07 commentedon Jun 11, 2026
@doughayden Thanks for folding in the workflow HITL path and confirming the ingest fix on a real OAuth EUC run — went through the updated #6007 and both builders now dump json-mode, with the regression tests sitting at exactly the right boundary. Nice that the LLM-flow one exercises the full runner path.
On the siblings: I'd keep them out of this PR. The tool-confirmation args at functions.py:368 share the same hazard surface — long-running function_call.args that memory ingest can serialize — so that's worth its own issue with a repro.
The actions dump near :1241 is an internal merge that gets re-validated into EventActions and never crosses a json.dumps boundary, so python-mode is fine there.
Nothing blocking from my side — PR's in review now!
Team is looking more into it.
Thanks!
doughayden commentedon Jun 11, 2026
Thanks @surajksharma07, sounds good! I'm happy to open a separate PR for those siblings if you feel the team would value that contribution. I'll refer to this issue in a fresh PR without creating a separate companion issue if that's easier/preferred.
surajksharma07 commentedon Jun 16, 2026
@doughayden Good catch, and that's on us, not you — check-file-contents.yml's googleapis.com/mTLS check scans the full file content of anything you touch, not just your diff.
Unlike the import-pattern/cli-import checks right above it in that same workflow, it never got a tests/.* exclusion, so the other 20 pre-existing fixtures get swept in just because you added two lines to that file.
Leave them alone — rewriting fixtures you didn't author is out of scope for a one-line serialization fix.
I'll get the workflow patched to add the same tests/.* exclusion its siblings already have and merge once review is otherwise green.
No need to touch test_functions_request_euc.py beyond your two lines!
doughayden commentedon Jun 16, 2026
Thanks @surajksharma07, makes sense. I'll leave the fixtures for your workflow patch then and won't push anything further.
fix: Make EUC request args JSON-serializable
fix: Make EUC request args JSON-serializable