API 400: cache_control TTL ordering violation in long sessions with many MCP tools

Resolved 💬 3 comments Opened Mar 27, 2026 by dirkenglund Closed Mar 30, 2026

Bug

Long Claude Code sessions with many MCP tools (40+) eventually hit this API error:

API Error: 400
{"type":"error","error":{"type":"invalid_request_error","message":"messages.1040.content.3.cache_control.ttl: a ttl='1h' cache_control block must not come after a ttl='5m' cache_control block. Note that blocks are processed in the following order: `tools`, `system`, `messages`."}}

Reproduction

  1. Start Claude Code with 10+ MCP servers (40+ tools total)
  2. Have a long conversation (1000+ message turns)
  3. Eventually the prompt assembly places a ttl='1h' block after a ttl='5m' block

Environment

  • Claude Code v2.1.83
  • Opus 4.6 (1M context)
  • macOS Darwin 24.6.0
  • 10+ MCP servers active (neo4j, graphiti, lean-lsp, axiomatic, playwright, github, etc.)

Analysis

The Anthropic API requires cache_control TTL blocks to be non-increasing order (longer durations first). Claude Code's internal prompt assembly violates this constraint when:

  • Tools (from MCP servers) are tagged with one TTL
  • System instructions are tagged with another TTL
  • Earlier messages in the conversation have a different TTL

The ordering tools → system → messages means if tools get ttl='5m' and system gets ttl='1h', it violates the monotonic constraint.

Impact

  • Session becomes unusable after the error
  • Only workaround is /clear to reset conversation
  • Particularly affects power users with many MCP servers and long sessions

Expected behavior

Claude Code should ensure TTL blocks are assembled in non-increasing order, or use a consistent TTL across all cached blocks.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗