spring-projects/spring-ai · error · RuntimeException
CloneNotSupportedException (wrapped RuntimeException)
Error message
CloneNotSupportedException (wrapped RuntimeException)
What it means
DefaultChatOptionsBuilder.clone() calls super.clone() and wraps any CloneNotSupportedException in a RuntimeException. Because the builder implements Cloneable this should never happen, so the wrapped exception indicates an internal JVM-level clone failure rather than a caller mistake.
Solutions
- Ensure your builder subclass (and all superclasses) implements Cloneable.
- Prefer constructing a fresh builder (options.builder()/mutate()) instead of relying on clone().
- If you control the code, override clone() to copy fields manually and avoid Object.clone().
Example fix
// before DefaultChatOptionsBuilder copy = builder.clone(); // after DefaultChatOptionsBuilder copy = DefaultChatOptionsBuilder.builder().from(builder.build());
Defensive patterns
Strategy: type-guard
Validate before calling
if (!(builder instanceof Cloneable)) { /* don't call clone() */ } Type guard
boolean cloneable(Object o) { return o instanceof Cloneable; } Try / catch
try { return builder.clone(); } catch (RuntimeException e) { return DefaultChatOptionsBuilder.builder().from(builder.build()); } Prevention
- Avoid clone(); use the builder's copy/from pattern instead
- Keep builder subclasses Cloneable if you rely on clone()
- Don't proxy or bytecode-enhance option builders in ways that drop interfaces
When it happens
Trigger: Invoking clone() on a DefaultChatOptionsBuilder (or subclass B) whose concrete class hierarchy fails Object.clone()'s Cloneable check.
Common situations: Practically only seen with custom subclasses of the builder that do not propagate Cloneable, or exotic bytecode/proxy frameworks stripping the interface.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Currently only methods with a single CreateMessageRequest…
- Unsupported exchange type
- Unsupported exchange type
- Unsupported exchange type
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/cb01da967c136396.
Report an issue: GitHub.
Appendix: source
Thrown at spring-ai-model/src/main/java/org/springframework/ai/chat/prompt/DefaultChatOptionsBuilder.java:56
protected @Nullable Double temperature;
protected @Nullable Integer topK;
protected @Nullable Double topP;
public DefaultChatOptionsBuilder() {
}
@Override
public B clone() {
try {
B copy = (B) super.clone();
copy.stopSequences = this.stopSequences == null ? null : new ArrayList<>(this.stopSequences);
return copy;
}
catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
protected B self() {
return (B) this;
}
@Override
public B model(@Nullable String model) {
this.model = model;
return self();
}
@Override
public B frequencyPenalty(@Nullable Double frequencyPenalty) {
this.frequencyPenalty = frequencyPenalty;
return self();View on GitHub (pinned to 98a7beda4f)