spring-projects/spring-ai · error · IllegalArgumentException

httpClientBuilderCustomizers cannot be combined with a pre-b

Error message

httpClientBuilderCustomizers cannot be combined with a pre-built anthropicClient because the HTTP layer is already constructed

What it means

AnthropicChatModel.Builder.build() rejects combining httpClientBuilderCustomizers with a pre-built AnthropicClient. The customizers work by re-configuring the underlying HTTP client builder; if you supplied an already-constructed client, the HTTP layer exists and cannot be customized, so the builder throws IllegalArgumentException to prevent silently ignored customizers.

Source

Thrown at models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatModel.java:1945

		 * to apply, replacing any customizers registered earlier on this builder. The
		 * order of the list is preserved when invoking the customizers.
		 * @param customizers the list of customizers
		 * @return this builder
		 * @since 2.0.0
		 */
		public Builder httpClientBuilderCustomizers(List<AnthropicHttpClientBuilderCustomizer> customizers) {
			Assert.notNull(customizers, "customizers cannot be null");
			this.httpClientCustomizers = new ArrayList<>(customizers);
			return this;
		}

		/**
		 * Builds a new {@link AnthropicChatModel} instance.
		 * @return the configured chat model
		 */
		public AnthropicChatModel build() {
			if (!this.httpClientCustomizers.isEmpty() && this.anthropicClient != null) {
				throw new IllegalArgumentException(
						"httpClientBuilderCustomizers cannot be combined with a pre-built anthropicClient "
								+ "because the HTTP layer is already constructed");
			}
			if (!this.httpClientCustomizers.isEmpty() && this.anthropicClientAsync != null) {
				throw new IllegalArgumentException(
						"httpClientBuilderCustomizers cannot be combined with a pre-built anthropicClientAsync "
								+ "because the HTTP layer is already constructed");
			}
			return new AnthropicChatModel(this.anthropicClient, this.anthropicClientAsync, this.options,
					this.toolCallingManager, this.observationRegistry, this.meterRegistry, this.dispatcherExecutor,
					this.httpClientCustomizers);
		}

	}

}

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Remove the pre-built anthropicClient and let the builder create it (pass baseUrl + apiKey instead) so customizers apply.
  2. Keep the pre-built client and drop the httpClientBuilderCustomizers, applying the customization when you construct the client yourself.
  3. If customizers target only the async client, at least ensure they are not applied together with the sync pre-built client per this check.
  4. Apply timeouts/proxies directly on the pre-built client's HTTP layer instead of via builder customizers.

Example fix

// before
builder.anthropicClient(preBuiltClient)
       .httpClientBuilderCustomizers(List.of(b -> b.readTimeout(Duration.ofSeconds(60))));
// after
builder.baseUrl("https://api.anthropic.com")
       .apiKey(apiKey)
       .httpClientBuilderCustomizers(List.of(b -> b.readTimeout(Duration.ofSeconds(60))));
Defensive patterns

Strategy: validation

Validate before calling

if (customizers != null && !customizers.isEmpty() && preBuiltClient != null) {
    throw new IllegalStateException("Choose either a pre-built anthropicClient OR httpClientBuilderCustomizers");
}

Try / catch

AnthropicChatModel model;
try {
    model = builder.build();
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("pre-built anthropicClient")) {
        builder = resetBuilderWithoutCustomizers();
        model = builder.build();
    } else throw e;
}

Prevention

When it happens

Trigger: Calling builder.anthropicClient(client) (or the constructor accepting a pre-built client) and also calling builder.httpClientBuilderCustomizers(...), then invoking build().

Common situations: Sharing a singleton AnthropicClient across models while also adding timeout/proxy/interceptor customizers; migrating configuration code that sets both options after a version upgrade introduced customizer support.

Related errors


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/2640c9c46858d2e8. Report an issue: GitHub.