Skip to content

DynamicCache.crop(0) retains the full KV cache and oversized negative crops retain stale tokens #47433

Description

@HoneyTyagii

DynamicCache.crop(0) retains the full KV cache and oversized negative crops retain stale tokens

System Info

  • Transformers source revision: 71554973d2c3123a23f2a1d6b7b63568b4e4df62
  • OS: Windows 10 (10.0.26200)
  • Python: 3.11.9
  • PyTorch: 2.13.0+cpu

Who can help?

Generation/cache maintainers.

Information

The problem occurs in a minimal standalone script and does not depend on a model, dataset, GPU, or network access.

Reproduction

import torch
from transformers import DynamicCache

key = torch.arange(3, dtype=torch.float32).reshape(1, 1, 3, 1)

cache = DynamicCache()
cache.update(key, key.clone(), layer_idx=0)
cache.crop(0)
print(cache.get_seq_length())  # 3, expected 0

cache = DynamicCache()
cache.update(key, key.clone(), layer_idx=0)
cache.crop(-5)
print(cache.get_seq_length())  # 1, expected 0

DynamicLayer.crop handles every max_length <= 0 as a relative crop:

if max_length <= 0:
    max_length = self.get_seq_length() - abs(max_length)

For crop(0), this computes the current sequence length and triggers the early return, so nothing is removed. For a three-token cache, crop(-5) computes -2; Python slicing with [..., :-2, :] then retains one stale token instead of producing an empty cache.

Expected behavior

  • crop(0) should empty initialized key and value tensors along the sequence dimension.
  • A negative value should remove that many trailing tokens.
  • Removing at least the current sequence length should either empty the cache or raise a clear validation error. It should never silently retain tokens.

This is important for rollback and cache-reuse flows, including speculative or custom generation. A complete rollback can silently preserve old key/value states, causing later decoding to attend to stale tokens or creating cache-position and attention-mask length mismatches.

Suggested implementation direction

  1. Treat only max_length < 0 as relative removal, keeping zero as an absolute target.
  2. Clamp the computed target to zero, or explicitly reject oversized negative removal.
  3. Audit sliding-window, hybrid, and composite cache layers so tensors and length metadata remain consistent.
  4. Add parameterized regression coverage for 2, 0, -1, -3, and -5, plus a full rollback followed by an append.

I searched existing open and closed issues for crop(0), DynamicCache.crop, negative cache crops, and stale cache tokens, and did not find a report for this behavior.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions