{"record":{"id":"15a28c508cec3333","repo":"spring-projects/spring-ai","slug":"empty-embedding-vector-returned-for-input-at-index","errorCode":null,"errorMessage":"Empty embedding vector returned for input at index + indexCounter.get() + . Skipping.","messagePattern":"Empty embedding vector returned for input at index \\+ indexCounter\\.get\\(\\) \\+ \\. Skipping\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/titan/BedrockTitanEmbeddingModel.java","lineNumber":117,"sourceCode":"\n\t\tfor (String inputContent : request.getInstructions()) {\n\t\t\tvar apiRequest = createTitanEmbeddingRequest(inputContent, request.getOptions());\n\n\t\t\ttry {\n\t\t\t\tTitanEmbeddingResponse response = Observation\n\t\t\t\t\t.createNotStarted(\"bedrock.embedding\", this.observationRegistry)\n\t\t\t\t\t.lowCardinalityKeyValue(\"model\", \"titan\")\n\t\t\t\t\t.lowCardinalityKeyValue(\"input_type\", this.inputType.name().toLowerCase(Locale.ROOT))\n\t\t\t\t\t.highCardinalityKeyValue(\"input_length\", String.valueOf(inputContent.length()))\n\t\t\t\t\t.observe(() -> {\n\t\t\t\t\t\tTitanEmbeddingResponse r = this.embeddingApi.embedding(apiRequest);\n\t\t\t\t\t\tAssert.notNull(r, \"Embedding API returned null response\");\n\t\t\t\t\t\treturn r;\n\t\t\t\t\t});\n\n\t\t\t\tif (response.embedding() == null || response.embedding().length == 0) {\n\t\t\t\t\tif (logger.isWarnEnabled()) {\n\t\t\t\t\t\tlogger.warn(\"Empty embedding vector returned for input at index \" + indexCounter.get()\n\t\t\t\t\t\t\t\t+ \". Skipping.\");\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tembeddings.add(new Embedding(response.embedding(), indexCounter.getAndIncrement()));\n\n\t\t\t\tif (response.inputTextTokenCount() != null) {\n\t\t\t\t\ttokenUsage += response.inputTextTokenCount();\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (Exception ex) {\n\t\t\t\tif (logger.isErrorEnabled()) {\n\t\t\t\t\tlogger.error(\"Titan API embedding failed for input at index \" + indexCounter.get() + \": \"\n\t\t\t\t\t\t\t+ summarizeInput(inputContent), ex);\n\t\t\t\t}\n\t\t\t\tthrow ex; // Optional: Continue instead of throwing if you want partial\n\t\t\t\t\t\t\t// success","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/titan/BedrockTitanEmbeddingModel.java#L99-L135","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nList<String> inputs = chunks; // may contain blank chunks\n// after\nList<String> inputs = chunks.stream().filter(c -> c != null && !c.isBlank()).toList();","handlingStrategy":"validation","validationCode":"List<String> safe = inputs.stream().filter(t -> t != null && !t.isBlank()).toList();\nif (safe.size() != inputs.size()) log.warn(\"Dropped {} blank inputs before Titan embedding\", inputs.size() - safe.size());","typeGuard":"static boolean hasEmptyEmbedding(Embedding e) { return e == null || e.getOutput() == null || e.getOutput().length == 0; }","tryCatchPattern":"EmbeddingResponse resp = titanModel.call(req);\nList<Embedding> valid = resp.getResults().stream().filter(e -> e.getOutput() != null && e.getOutput().length > 0).toList();\nif (valid.size() < inputs.size()) { /* re-embed or fail loudly */ }","preventionTips":["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"],"tags":["aws-bedrock","embedding","empty-response","data-quality"],"backgroundTag":"empty-api-response","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"}