spring-projects/spring-ai · warning
Anthropic cache breakpoint limit (4) reached. Additional…
Error message
Anthropic cache breakpoint limit (4) reached. Additional cache_control directives will be ignored. Consider using fewer cache strategies or simpler content structure.
What it means
A warning from CacheBreakpointTracker.use() when more than 4 cache_control breakpoints are requested in a single Anthropic request. The Anthropic API caps prompt caching at 4 breakpoints; the tracker stops counting and warns once that additional cache_control directives will be ignored, so those content parts will not be cached.
Solutions
- Reduce cache_control breakpoints to at most 4, placing them at the most stable, longest-lived boundaries (tools, system, earliest messages)
- Move the single breakpoint to the last message instead of marking every message
- Consolidate content: merge cached segments so fewer breakpoints cover more tokens
- Audit prompt-building code for per-message breakpoint additions in loops
- Suppress irrelevant directives on volatile content (short-lived messages) that does not benefit from caching
Example fix
// before eachMessage.addCacheBreakpoint(); // >4 messages -> overflow ignored // after // put one breakpoint on last (stable) content to cover everything before it messages.get(messages.size() - 1).addCacheBreakpoint();
Defensive patterns
Strategy: validation
Validate before calling
// count cache breakpoints before building the request
long breakpoints = contentParts.stream().filter(ContentPart::hasCacheControl).count();
if (breakpoints > 4) {
throw new IllegalArgumentException("Max 4 Anthropic cache breakpoints, got " + breakpoints);
} Try / catch
// warning only (no exception): detect via logging and adjust prompt construction
if (logContains("cache breakpoint limit")) {
// rebuild prompt with fewer cache_control markers
} Prevention
- Cap cache_control markers at 4 per request; place them at stable boundaries (tools, system, oldest messages)
- Use a single breakpoint on the last message to cache the entire prefix
- Do not add a breakpoint per message in loops over conversation history
- Exclude volatile content (recent messages) from caching
- Review prompt-builder code when switching between caching strategies to avoid double-marking
When it happens
Trigger: Building a Prompt whose system text, messages, and/or tools collectively carry more than 4 CacheBreakpoint/ContentPart cache-control markers, then calling the chat model — each marker calls tracker.use(), and the 5th onward triggers the warning.
Common situations: Caching every tool definition plus system plus several history messages; combining multiple caching strategies (system, tools, conversation) without counting; generated prompts that add a breakpoint per message in long conversations.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Anthropic Citations API requires all documents to have…
- Failed to parse tool arguments JSON: + argumentsJson
- httpClientBuilderCustomizers cannot be combined with a…
- httpClientBuilderCustomizers cannot be combined with a…
- Invalid filename for file '':
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/64df7fad0fb7c385.
Report an issue: GitHub.
Appendix: source
Thrown at models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/CacheBreakpointTracker.java:51
private int count = 0;
private boolean hasWarned = false;
public boolean canUse() {
return this.count < 4;
}
public boolean allBreakpointsAreUsed() {
return !this.canUse();
}
public void use() {
if (this.count < 4) {
this.count++;
}
else if (!this.hasWarned) {
logger.warn(
"Anthropic cache breakpoint limit (4) reached. Additional cache_control directives will be ignored. "
+ "Consider using fewer cache strategies or simpler content structure.");
this.hasWarned = true;
}
}
public int getCount() {
return this.count;
}
}
View on GitHub (pinned to 98a7beda4f)