🔴 Required Information
Describe the Bug:
When context caching is enabled for an agent with a large, stable system_instruction and tools, GeminiContextCacheManager gets stuck trying to create a cache with an empty contents list.
From the second turn onward, every request logs:
Failed to create cache: contents are required.
As a result, no cache is ever created, and every turn performs a failed caches.create() call.
The issue is that the cacheable prefix can legitimately be 0 on the first turn (when only trailing user messages are present). That 0 is then reused when creating the cache, resulting in:
contents = llm_request.contents[:0] # []
The GenAI SDK treats an empty list differently from None: contents=[] raises ValueError("contents are required."), while contents=None is valid when system_instruction and tools are provided.
Passing None instead of an empty list would allow the cache to be created successfully.
Steps to Reproduce:
- Install
google-adk==2.4.0.
- Build an
App with context_cache_config=ContextCacheConfig() and a root LlmAgent whose system_instruction + tools comfortably exceed the 4096-token minimum and don't change between turns.
- Run a normal multi-turn session (turn 1 = a single user message).
- From turn 2 onward, observe the warning below on every turn;
cache_metadata.cache_name stays None.
Expected Behavior:
When the cacheable content prefix is empty (cache_contents_count == 0), the stable system_instruction + tools should still be cached (or creation cleanly skipped). The manager must not send contents=[] and then permanently skip caching.
Observed Behavior:
Cache creation fails on every turn and is never established:
WARNING [google_adk.google.adk.models.gemini_context_cache_manager] [gemini_context_cache_manager.py:352] - Failed to create cache: contents are required.
Environment Details:
- ADK Library Version (
pip show google-adk): 2.4.0
- Desktop OS: macOS (also reproduces on Linux / Cloud Run)
- Python Version (
python -V): 3.12
Model Information:
- Are you using LiteLLM: No
- Which model is being used: gemini-3.1-flash-lite (Vertex AI)
🟡 Optional Information
Regression:
Yes. Worked in 2.3.0. The contents_count = 0 seed was introduced by commit 7c7f1e7 (PR #6067, "fix: fingerprint cacheable context prefix", Fixes #6062), which changed the fingerprint-only seed from len(llm_request.contents) (always ≥ 1) to _find_count_of_contents_to_cache(...) (returns 0 for a single trailing user batch). The prefix-token size gate added in #6137 (Fixes #5847) does not catch the empty prefix because it still counts system_instruction + tools.
Logs:
WARNING [google_adk.google.adk.models.gemini_context_cache_manager] [gemini_context_cache_manager.py:352] - Failed to create cache: contents are required. [genAiConversationId= gcpVertexAgentInvocationId= gcpVertexAgentEventId=]
How often has this issue occurred?:
- Always (100%) — for agents with a large, stable system instruction + tools.
🔴 Required Information
Describe the Bug:
When context caching is enabled for an agent with a large, stable
system_instructionand tools,GeminiContextCacheManagergets stuck trying to create a cache with an emptycontentslist.From the second turn onward, every request logs:
As a result, no cache is ever created, and every turn performs a failed
caches.create()call.The issue is that the cacheable prefix can legitimately be
0on the first turn (when only trailing user messages are present). That0is then reused when creating the cache, resulting in:The GenAI SDK treats an empty list differently from
None:contents=[]raisesValueError("contents are required."), whilecontents=Noneis valid whensystem_instructionandtoolsare provided.Passing
Noneinstead of an empty list would allow the cache to be created successfully.Steps to Reproduce:
google-adk==2.4.0.Appwithcontext_cache_config=ContextCacheConfig()and a rootLlmAgentwhosesystem_instruction+ tools comfortably exceed the 4096-token minimum and don't change between turns.cache_metadata.cache_namestaysNone.Expected Behavior:
When the cacheable content prefix is empty (
cache_contents_count == 0), the stablesystem_instruction+ tools should still be cached (or creation cleanly skipped). The manager must not sendcontents=[]and then permanently skip caching.Observed Behavior:
Cache creation fails on every turn and is never established:
Environment Details:
pip show google-adk): 2.4.0python -V): 3.12Model Information:
🟡 Optional Information
Regression:
Yes. Worked in 2.3.0. The
contents_count = 0seed was introduced by commit7c7f1e7(PR #6067, "fix: fingerprint cacheable context prefix", Fixes #6062), which changed the fingerprint-only seed fromlen(llm_request.contents)(always ≥ 1) to_find_count_of_contents_to_cache(...)(returns0for a single trailing user batch). The prefix-token size gate added in #6137 (Fixes #5847) does not catch the empty prefix because it still countssystem_instruction+ tools.Logs:
How often has this issue occurred?: