{"record":{"id":"2640c9c46858d2e8","repo":"spring-projects/spring-ai","slug":"httpclientbuildercustomizers-cannot-be-combined-wi","errorCode":null,"errorMessage":"httpClientBuilderCustomizers cannot be combined with a pre-built anthropicClient because the HTTP layer is already constructed","messagePattern":"httpClientBuilderCustomizers cannot be combined with a pre-built anthropicClient because the HTTP layer is already constructed","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatModel.java","lineNumber":1945,"sourceCode":"\t\t * to apply, replacing any customizers registered earlier on this builder. The\n\t\t * order of the list is preserved when invoking the customizers.\n\t\t * @param customizers the list of customizers\n\t\t * @return this builder\n\t\t * @since 2.0.0\n\t\t */\n\t\tpublic Builder httpClientBuilderCustomizers(List<AnthropicHttpClientBuilderCustomizer> customizers) {\n\t\t\tAssert.notNull(customizers, \"customizers cannot be null\");\n\t\t\tthis.httpClientCustomizers = new ArrayList<>(customizers);\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Builds a new {@link AnthropicChatModel} instance.\n\t\t * @return the configured chat model\n\t\t */\n\t\tpublic AnthropicChatModel build() {\n\t\t\tif (!this.httpClientCustomizers.isEmpty() && this.anthropicClient != null) {\n\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\"httpClientBuilderCustomizers cannot be combined with a pre-built anthropicClient \"\n\t\t\t\t\t\t\t\t+ \"because the HTTP layer is already constructed\");\n\t\t\t}\n\t\t\tif (!this.httpClientCustomizers.isEmpty() && this.anthropicClientAsync != null) {\n\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\"httpClientBuilderCustomizers cannot be combined with a pre-built anthropicClientAsync \"\n\t\t\t\t\t\t\t\t+ \"because the HTTP layer is already constructed\");\n\t\t\t}\n\t\t\treturn new AnthropicChatModel(this.anthropicClient, this.anthropicClientAsync, this.options,\n\t\t\t\t\tthis.toolCallingManager, this.observationRegistry, this.meterRegistry, this.dispatcherExecutor,\n\t\t\t\t\tthis.httpClientCustomizers);\n\t\t}\n\n\t}\n\n}\n","sourceCodeStart":1927,"sourceCodeEnd":1962,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatModel.java#L1927-L1962","documentation":"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.","triggerScenarios":"Calling builder.anthropicClient(client) (or the constructor accepting a pre-built client) and also calling builder.httpClientBuilderCustomizers(...), then invoking build().","commonSituations":"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.","solutions":["Remove the pre-built anthropicClient and let the builder create it (pass baseUrl + apiKey instead) so customizers apply.","Keep the pre-built client and drop the httpClientBuilderCustomizers, applying the customization when you construct the client yourself.","If customizers target only the async client, at least ensure they are not applied together with the sync pre-built client per this check.","Apply timeouts/proxies directly on the pre-built client's HTTP layer instead of via builder customizers."],"exampleFix":"// before\nbuilder.anthropicClient(preBuiltClient)\n       .httpClientBuilderCustomizers(List.of(b -> b.readTimeout(Duration.ofSeconds(60))));\n// after\nbuilder.baseUrl(\"https://api.anthropic.com\")\n       .apiKey(apiKey)\n       .httpClientBuilderCustomizers(List.of(b -> b.readTimeout(Duration.ofSeconds(60))));","handlingStrategy":"validation","validationCode":"if (customizers != null && !customizers.isEmpty() && preBuiltClient != null) {\n    throw new IllegalStateException(\"Choose either a pre-built anthropicClient OR httpClientBuilderCustomizers\");\n}","typeGuard":null,"tryCatchPattern":"AnthropicChatModel model;\ntry {\n    model = builder.build();\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"pre-built anthropicClient\")) {\n        builder = resetBuilderWithoutCustomizers();\n        model = builder.build();\n    } else throw e;\n}","preventionTips":["Pick one configuration style: either supply clients or supply customizers, never both.","If you must customize HTTP, let the builder construct the client from baseUrl+apiKey.","Write a unit test that calls build() with your production builder configuration."],"tags":["java","spring-ai","anthropic","builder","conflicting-options"],"backgroundTag":"conflicting-config-options","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}