spring-projects/spring-ai · warning
Empty embedding vector returned for input at index + indexCo
Error message
Empty embedding vector returned for input at index + indexCounter.get() + . Skipping.
What it means
Warning logged inside BedrockTitanEmbeddingModel.call() when the Titan invoke response for a given input contains a null or zero-length embedding vector. The input at that index is skipped entirely — no Embedding is added to the result — so the returned EmbeddingResponse has fewer embeddings than the request had instructions, and index numbering shifts accordingly.
Source
Thrown at models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/titan/BedrockTitanEmbeddingModel.java:117
for (String inputContent : request.getInstructions()) {
var apiRequest = createTitanEmbeddingRequest(inputContent, request.getOptions());
try {
TitanEmbeddingResponse response = Observation
.createNotStarted("bedrock.embedding", this.observationRegistry)
.lowCardinalityKeyValue("model", "titan")
.lowCardinalityKeyValue("input_type", this.inputType.name().toLowerCase(Locale.ROOT))
.highCardinalityKeyValue("input_length", String.valueOf(inputContent.length()))
.observe(() -> {
TitanEmbeddingResponse r = this.embeddingApi.embedding(apiRequest);
Assert.notNull(r, "Embedding API returned null response");
return r;
});
if (response.embedding() == null || response.embedding().length == 0) {
if (logger.isWarnEnabled()) {
logger.warn("Empty embedding vector returned for input at index " + indexCounter.get()
+ ". Skipping.");
}
continue;
}
embeddings.add(new Embedding(response.embedding(), indexCounter.getAndIncrement()));
if (response.inputTextTokenCount() != null) {
tokenUsage += response.inputTextTokenCount();
}
}
catch (Exception ex) {
if (logger.isErrorEnabled()) {
logger.error("Titan API embedding failed for input at index " + indexCounter.get() + ": "
+ summarizeInput(inputContent), ex);
}
throw ex; // Optional: Continue instead of throwing if you want partial
// successView on GitHub (pinned to 98a7beda4f)
Solutions
- Sanitize inputs before calling: filter out null/blank strings from the instruction list.
- Check that the returned embeddings count matches the input count and re-embed skipped inputs.
- Verify the Titan model ID and region are correct; an unsupported model/region can yield degenerate responses.
- Retry the failed input individually if the empty vector looks transient.
Example fix
// before List<String> inputs = chunks; // may contain blank chunks // after List<String> inputs = chunks.stream().filter(c -> c != null && !c.isBlank()).toList();
Defensive patterns
Strategy: validation
Validate before calling
List<String> safe = inputs.stream().filter(t -> t != null && !t.isBlank()).toList();
if (safe.size() != inputs.size()) log.warn("Dropped {} blank inputs before Titan embedding", inputs.size() - safe.size()); Type guard
static boolean hasEmptyEmbedding(Embedding e) { return e == null || e.getOutput() == null || e.getOutput().length == 0; } Try / catch
EmbeddingResponse resp = titanModel.call(req);
List<Embedding> valid = resp.getResults().stream().filter(e -> e.getOutput() != null && e.getOutput().length > 0).toList();
if (valid.size() < inputs.size()) { /* re-embed or fail loudly */ } Prevention
- Never pass blank or whitespace-only chunks to embedding models
- Assert embeddings count == inputs count after every call
- Log input length distribution during ingestion to catch degenerate chunks
When it happens
Trigger: Titan returns HTTP 200 but embedding()==null or embedding().length==0 for one of the per-input invocations — e.g. empty/whitespace-only input text, input that Titan silently rejected, or a malformed model response body.
Common situations: Ingesting documents where some chunks are empty strings after splitting; requests containing only whitespace or control characters; intermittent Bedrock issues producing empty bodies; vector-store upserts later failing because of mismatched embedding counts.
Understand the failure class
Background: "empty response", "returned no data", "empty embeddings": what HTTP 200-with-empty-body errors mean across libraries — this error's family across 36 libraries.
Related errors
- Titan Embedding does not support batch embedding. Multiple A
- Required properties for TitanEmbeddingBedrockApi are missing
- InputType property for BedrockTitanEmbeddingModel is missing
- No embedding input is provided - all texts are null or empty
- model cannot be null or empty
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/15a28c508cec3333.
Report an issue: GitHub.