conductor-oss/conductor · error · IOException
Embeddings API failed with status %d: %s
Error message
Embeddings API failed with status %d: %s
What it means
OpenAIEmbeddingsApi.createEmbeddings() throws IOException with message "Embeddings API failed with status %d: %s" when the HTTP response is not 2xx. The %d is the HTTP status code, %s is the raw response body. This is the low-level OkHttp client for POST {baseUrl}/embeddings. The auth header is configurable (Bearer token or api-key for Azure).
Source
Thrown at ai/src/main/java/org/conductoross/conductor/ai/providers/openai/api/OpenAIEmbeddingsApi.java:75
this(httpClient, apiKey, baseUrl, false);
}
public EmbeddingResult createEmbeddings(EmbeddingRequest request) throws IOException {
String jsonBody = objectMapper.writeValueAsString(request);
Request httpRequest =
new Request.Builder()
.url(baseUrl + "/embeddings")
.header(authHeaderName, authHeaderValue)
.header("Content-Type", "application/json")
.post(RequestBody.create(jsonBody, JSON))
.build();
try (Response response = httpClient.newCall(httpRequest).execute()) {
ResponseBody body = response.body();
String responseBody = body != null ? body.string() : "";
if (!response.isSuccessful()) {
throw new IOException(
"Embeddings API failed with status %d: %s"
.formatted(response.code(), responseBody));
}
return objectMapper.readValue(responseBody, EmbeddingResult.class);
}
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public record EmbeddingRequest(String model, String input, Integer dimensions) {}
@JsonIgnoreProperties(ignoreUnknown = true)
public record EmbeddingResult(String object, List<EmbeddingData> data, String model) {}
@JsonIgnoreProperties(ignoreUnknown = true)
public record EmbeddingData(String object, Integer index, List<Float> embedding) {}
}
View on GitHub (pinned to cf7c3e4a8a)
Solutions
- Read the status code and body from the IOException message.
- For 401: verify the API key is valid and not expired.
- For 429: implement batch processing with rate-limit-aware backoff; embeddings have per-minute token limits.
- For 400: check if the dimensions parameter is valid for the model (ada-002 doesn't support custom dimensions).
- For 400 input-too-long: chunk the input text before embedding.
Example fix
// before
new OpenAIEmbeddingsApi.EmbeddingRequest("text-embedding-ada-002", veryLongText, 256)
// after — ada-002 doesn't support custom dimensions
new OpenAIEmbeddingsApi.EmbeddingRequest("text-embedding-ada-002", veryLongText, null)
// or use a model that supports dimensions
new OpenAIEmbeddingsApi.EmbeddingRequest("text-embedding-3-small", veryLongText, 256) Defensive patterns
Strategy: retry
Validate before calling
// Validate embedding request before calling
OpenAIEmbeddingsApi.EmbeddingRequest request = /* ... */;
if (request.model() == null || request.model().isBlank()) {
throw new IllegalArgumentException("Embedding model is required");
}
if (request.input() == null || request.input().isBlank()) {
throw new IllegalArgumentException("Input text is required");
}
// Validate dimensions is only set for models that support it
if (request.dimensions() != null && request.model().equals("text-embedding-ada-002")) {
throw new IllegalArgumentException(
"text-embedding-ada-002 does not support custom dimensions; use text-embedding-3-small/large");
} Type guard
null
Try / catch
int maxRetries = 3;
for (int attempt = 0; attempt <= maxRetries; attempt++) {
try {
return api.createEmbeddings(request);
} catch (IOException e) {
String msg = e.getMessage();
if (msg.contains("429") && attempt < maxRetries) {
long delay = (long) Math.pow(2, attempt) * 2000; // longer backoff for rate limits
Thread.sleep(delay);
continue;
}
throw e;
}
} Prevention
- Validate the embedding model name is a supported OpenAI embeddings model.
- Don't set dimensions for text-embedding-ada-002 (it doesn't support it).
- Implement batch processing with rate-limit-aware backoff for bulk indexing.
- Chunk long input text to avoid exceeding the model's token limit.
- Monitor per-minute token usage to stay under rate limits.
When it happens
Trigger: POST {baseUrl}/embeddings returns non-2xx. Common: 401 (invalid/expired API key), 429 (rate limit — embeddings are high-volume so this is frequent), 404 (wrong baseURL or model not found), 400 (invalid dimensions parameter for the model, input too long), 500 (server error).
Common situations: Expired API key; requesting dimensions on a model that doesn't support it (e.g. text-embedding-ada-002 ignores dimensions; text-embedding-3-small/large support it); input text exceeding the model's token limit; rate limit during bulk vector-store indexing; wrong baseURL.
Related errors
- Embeddings API call failed:
- Image Generation API failed with status %d: %s
- Responses API failed with status %d: %s
- Speech API call failed:
- Image generation API call failed:
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/8403045f927b2e75.
Report an issue: GitHub.