Skip to content

Context cache creation fails with 'contents are required' when cacheable prefix is empty (cache_contents_count == 0) #6363

Closed

Description

@pp-azhoraven

🔴 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:

  1. Install google-adk==2.4.0.
  2. 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.
  3. Run a normal multi-turn session (turn 1 = a single user message).
  4. 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.

Activity

  1. hxaxd commented on Jul 10, 2026

    @hxaxd
    Contributor

    Thanks for the detailed report. I checked the current code and history, and the diagnosis looks correct.

    PR #6067 had a reasonable goal: exclude request-scoped trailing user contents from the stable cache fingerprint. A zero-length content prefix is therefore valid; the regression is at the SDK boundary, where that zero becomes contents=[] instead of None.

    The existing zero-prefix tests mock caches.create() but do not inspect config.contents, so the invalid empty list is accepted by the mock.

    I’d like to submit a focused fix that passes None for an empty prefix and adds a regression test for the zero-prefix case. Would it be okay for me to take this?

  2. pp-azhoraven commented on Jul 10, 2026

    @pp-azhoraven
    Author

    Hey @hxaxd , I think this proposal only fixes the issue partially. It removes the warning, but the cache still won't be created.

    cache_contents_count should be derived from _find_count_of_contents_to_cache(llm_request.contents) rather than old_cache_metadata.contents_count (which is a stale 0). Additionally, the failure path should re-reserve using the current count so that it converges over time instead of getting permanently stuck at 0

  3. hxaxd commented on Jul 10, 2026

    @hxaxd
    Contributor

    Hey @pp-azhoraven, thanks for taking a look. I’d like to clarify two misunderstandings here.

    First, old_cache_metadata.contents_count is not a stale live count. It is the prefix length paired with the stored fingerprint, so ADK must reuse it to compare the same cache identity. Recomputing it on every request would turn the prefix into a moving target—roughly 0, 2, 4, 6 in a normal conversation. Each new fingerprint would then fail to match the previous one, and ADK would keep reseeding fingerprint-only metadata without reaching caches.create().

    Second, contents=None does not mean no cache is created. It only omits conversation contents; the system instruction and tools are still sent to caches.create(). Once that call succeeds, ADK receives and immediately applies a cache_name. Preserving the original count after a transient failure is also intentional: it lets the next request retry the same cache identity. Re-seeding after an operational failure would at best add another fingerprint-only round and, combined with a continuously recalculated count, could prevent cache creation indefinitely.

    So the issue is the [] versus None SDK boundary, not a stale prefix count.

  4. pp-azhoraven commented on Jul 10, 2026

    @pp-azhoraven
    Author

    @hxaxd , thank you for clarification! Then your fix is reasonable

  5. added
    agent config[Component] This issue is related to the Agent Config interface and implementation
    on Jul 13, 2026
  6. added a commit that references this issue on Jul 13, 2026
    ee7174d
  7. added a commit that references this issue on Aug 11, 2026
    34bb489
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

agent config[Component] This issue is related to the Agent Config interface and implementation

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions