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

  1. Ensure your builder subclass (and all superclasses) implements Cloneable.
  2. Prefer constructing a fresh builder (options.builder()/mutate()) instead of relying on clone().
  3. 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

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


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)