spring-projects/spring-ai · error · RuntimeException
Could not add document
Error message
Could not add document: {0} What it means
RedisVectorStore.doAdd() writes documents through a Jedis pipeline and checks every response against the expected OK reply. If any single document write in the batch returned an error response, it logs the offending reply and throws a RuntimeException with that response embedded in the message. This means at least one document in the add batch failed at the Redis server side (e.g. JSON.SET rejected).
Solutions
- Check the embedded response in the message to identify the failing command and fix the server-side cause
- Verify Redis has RedisJSON and RediSearch modules loaded (redis-modules.json / Redis Stack)
- Inspect the documents in the failing batch for values that break JSON serialization
- Ensure the target Redis instance is writable and not a read-only replica
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check: ensure modules and writability
String modules = jedisClient.info("modules"); // expect search & ReJSON
if (modules == null || !modules.contains("search")) throw new IllegalStateException("Redis Stack modules missing"); Try / catch
try { store.add(docs); } catch (RuntimeException e) { if (e.getMessage().startsWith("Could not add document:")) { /* inspect failing reply, retry batch individually */ } } Prevention
- Install Redis Stack (RedisJSON + RediSearch)
- Validate document metadata serializes to clean JSON
- On batch failure, retry documents one-by-one to isolate the bad one
- Avoid writing to read-only replicas
When it happens
Trigger: Adding a batch of documents where at least one pipeline response is not 'OK', e.g. RedisJSON module missing, malformed resulting JSON document, key type conflicts, or OOM/replica read-only errors on the server.
Common situations: Redis server without the RediSearch/RedisJSON modules loaded; document metadata containing values that cannot serialize to JSON; index/schema mismatch after upgrading Redis; writing to a read-only replica.
Related errors
- Could not create index
- Expression type not supported for numeric fields
- Failed to delete documents by filter
- Failed to delete some documents
- Failed to execute count query
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/85263c326c13e0b8.
Report an issue: GitHub.
Appendix: source
Thrown at vector-stores/spring-ai-redis-store/src/main/java/org/springframework/ai/vectorstore/redis/RedisVectorStore.java:383
var fields = new HashMap<String, Object>();
float[] embedding = embeddings.get(i);
// Normalize embeddings for COSINE distance metric
if (this.distanceMetric == DistanceMetric.COSINE) {
embedding = normalize(embedding);
}
fields.put(this.embeddingFieldName, embedding);
fields.put(this.contentFieldName, document.getText());
fields.putAll(document.getMetadata());
pipeline.jsonSetWithEscape(key(document.getId()), JSON_SET_PATH, fields);
}
List<Object> responses = pipeline.syncAndReturnAll();
Optional<Object> errResponse = responses.stream().filter(Predicate.not(RESPONSE_OK)).findAny();
if (errResponse.isPresent()) {
String message = MessageFormat.format("Could not add document: {0}", errResponse.get());
logger.error(message);
throw new RuntimeException(message);
}
}
}
private String key(String id) {
return this.prefix + id;
}
@Override
public void doDelete(List<String> idList) {
try (Pipeline pipeline = this.jedisClient.pipelined()) {
for (String id : idList) {
pipeline.jsonDel(key(id));
}
List<Object> responses = pipeline.syncAndReturnAll();
Optional<Object> errResponse = responses.stream().filter(Predicate.not(RESPONSE_DEL_OK)).findAny();
if (errResponse.isPresent()) {
if (logger.isErrorEnabled()) {View on GitHub (pinned to 98a7beda4f)