conductor-oss/conductor · error · RuntimeException
Anthropic Messages API call failed: {message}
Error message
Anthropic Messages API call failed: {message} What it means
AnthropicChatModel.call() wraps any java.io.IOException thrown by AnthropicMessagesApi.createMessage() into a RuntimeException with this message. The underlying IOException (connection timeout, read timeout, DNS failure, TLS error) is preserved as the cause. This is the catch-all for all transport-layer failures between Conductor and api.anthropic.com; HTTP error responses (non-2xx status codes) are handled separately inside createMessage itself (see error 182).
Source
Thrown at ai/src/main/java/org/conductoross/conductor/ai/providers/anthropic/AnthropicChatModel.java:72
public class AnthropicChatModel implements ChatModel {
private static final int DEFAULT_MAX_TOKENS = 8192;
private final AnthropicMessagesApi messagesApi;
private final ObjectMapper objectMapper = new ObjectMapper();
public AnthropicChatModel(AnthropicMessagesApi messagesApi) {
this.messagesApi = messagesApi;
}
@Override
public ChatResponse call(Prompt prompt) {
try {
MessagesRequest request = buildRequest(prompt);
MessagesResponse result = messagesApi.createMessage(request);
return toSpringChatResponse(result, prompt.getOptions());
} catch (IOException e) {
throw new RuntimeException("Anthropic Messages API call failed: " + e.getMessage(), e);
}
}
private MessagesRequest buildRequest(Prompt prompt) {
List<org.springframework.ai.chat.messages.Message> springMessages =
prompt.getInstructions();
ChatOptions options = prompt.getOptions();
// Extract system messages
String system = null;
List<org.springframework.ai.chat.messages.Message> nonSystemMessages = new ArrayList<>();
for (org.springframework.ai.chat.messages.Message msg : springMessages) {
if (msg.getMessageType() == MessageType.SYSTEM) {
String sysText = ((SystemMessage) msg).getText();
system = system == null ? sysText : system + "\n" + sysText;
} else {
nonSystemMessages.add(msg);
}View on GitHub (pinned to cf7c3e4a8a)
Solutions
- Inspect the cause (getCause()) and its message — it carries the specific I/O failure reason.
- Verify network connectivity to config.getBaseURL() (default https://api.anthropic.com) from the Conductor host.
- If the request is large (many tokens, multi-image), increase the OkHttp readTimeout via AIHttpClients configuration.
- If behind a proxy, set the appropriate OkHttp proxy configuration.
Example fix
// before — default client with short timeout
Anthropic anthropic = new Anthropic(config);
// after — custom client with longer timeout
OkHttpClient httpClient = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(120, TimeUnit.SECONDS)
.build();
Anthropic anthropic = new Anthropic(config, httpClient); Defensive patterns
Strategy: retry
Validate before calling
// Validate Anthropic config before calling the chat model
void validateAnthropicConfig(AnthropicConfiguration config) {
if (config.getApiKey() == null || config.getApiKey().isBlank()) {
throw new IllegalArgumentException("Anthropic API key is required");
}
if (config.getBaseURL() == null || config.getBaseURL().isBlank()) {
throw new IllegalArgumentException("Anthropic base URL is required");
}
} Try / catch
// Retry on transient IOException, fail fast on permanent errors
int maxRetries = 3;
for (int attempt = 0; attempt <= maxRetries; attempt++) {
try {
return chatModel.call(prompt);
} catch (RuntimeException e) {
if (e.getCause() instanceof java.io.IOException
&& attempt < maxRetries) {
Thread.sleep((long) Math.pow(2, attempt) * 1000);
continue;
}
throw e;
}
} Prevention
- Configure OkHttp with generous connect/read timeouts (30s/120s) for Claude API calls via a custom OkHttpClient passed to the Anthropic constructor.
- Verify network connectivity to api.anthropic.com from the Conductor host before deploying.
- Log the cause exception (getCause()) to distinguish transport failures from API rejections.
- Use exponential backoff retry for transient IOException causes.
When it happens
Trigger: The OkHttp POST to {baseUrl}/v1/messages fails at the transport layer: socket timeout, connection refused, DNS resolution failure for api.anthropic.com, TLS handshake failure, or the OkHttp client's readTimeout is exceeded for a large streaming-adjacent request.
Common situations: OkHttp default timeout too short for large-context Claude requests. Corporate proxy or firewall blocking api.anthropic.com. Incorrect baseUrl configured in AnthropicConfiguration pointing to an unreachable host. Intermittent network partition or DNS blip in containerised deployments.
Related errors
- Gemini generateContent failed: {message}
- Embeddings API call failed: {message}
- Gemini generateImages failed: {message}
- Gemini embedContent failed
- Failed to download from {url}
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/0e3d585a88f369d3.
Report an issue: GitHub.