LangChain4j integration for Chroma embedding store enabling storage, retrieval, and similarity search of vector embeddings with metadata filtering support for both API V1 and V2.
Comprehensive guide to handling errors when using ChromaEmbeddingStore.
try {
ChromaEmbeddingStore store = ChromaEmbeddingStore.builder()
.baseUrl("http://localhost:8000")
.build();
store.add(embedding);
} catch (java.net.http.HttpConnectTimeoutException e) {
// Cannot connect to Chroma server
System.err.println("Connection failed: " + e.getMessage());
// Action: Check server is running, verify baseUrl
} catch (java.net.ConnectException e) {
// Connection refused
System.err.println("Connection refused: " + e.getMessage());
// Action: Ensure Chroma server is started
}try {
EmbeddingSearchResult<TextSegment> result = store.search(request);
} catch (java.net.http.HttpTimeoutException e) {
// Operation exceeded timeout
System.err.println("Operation timed out: " + e.getMessage());
// Action: Increase timeout or reduce operation size
}try {
ChromaEmbeddingStore store = ChromaEmbeddingStore.builder()
// Missing baseUrl
.collectionName("test")
.build();
} catch (IllegalArgumentException e) {
// Invalid configuration
System.err.println("Configuration error: " + e.getMessage());
// Action: Fix configuration
}public void addDocument(Embedding embedding, TextSegment segment) {
try {
store.add(embedding, segment);
} catch (Exception e) {
System.err.println("Failed to add document: " + e.getMessage());
e.printStackTrace();
}
}public String addWithRetry(
Embedding embedding,
TextSegment segment,
int maxRetries
) {
int attempt = 0;
Exception lastException = null;
while (attempt < maxRetries) {
try {
return store.add(embedding, segment);
} catch (java.net.http.HttpTimeoutException |
java.net.http.HttpConnectTimeoutException e) {
lastException = e;
attempt++;
if (attempt < maxRetries) {
System.out.println("Retry " + attempt + " of " + maxRetries);
try {
Thread.sleep(1000 * attempt); // Exponential backoff
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted during retry", ie);
}
}
} catch (Exception e) {
// Non-retryable error
throw new RuntimeException("Failed to add document", e);
}
}
throw new RuntimeException(
"Failed after " + maxRetries + " attempts",
lastException
);
}public class CircuitBreakerStore {
private final ChromaEmbeddingStore store;
private int failureCount = 0;
private long lastFailureTime = 0;
private static final int FAILURE_THRESHOLD = 5;
private static final long RESET_TIMEOUT = 60000; // 1 minute
private boolean isCircuitOpen() {
if (failureCount >= FAILURE_THRESHOLD) {
long timeSinceFailure = System.currentTimeMillis() - lastFailureTime;
if (timeSinceFailure < RESET_TIMEOUT) {
return true; // Circuit still open
} else {
// Try to reset
failureCount = 0;
return false;
}
}
return false;
}
public String add(Embedding embedding, TextSegment segment) {
if (isCircuitOpen()) {
throw new RuntimeException("Circuit breaker is open");
}
try {
String id = store.add(embedding, segment);
failureCount = 0; // Reset on success
return id;
} catch (Exception e) {
failureCount++;
lastFailureTime = System.currentTimeMillis();
throw e;
}
}
}public class ResilientRAG {
private final ChromaEmbeddingStore primaryStore;
private final ChromaEmbeddingStore backupStore; // Optional backup
public EmbeddingSearchResult<TextSegment> search(
EmbeddingSearchRequest request
) {
try {
return primaryStore.search(request);
} catch (Exception e) {
System.err.println("Primary store failed: " + e.getMessage());
if (backupStore != null) {
try {
System.out.println("Trying backup store");
return backupStore.search(request);
} catch (Exception backupError) {
System.err.println("Backup store also failed");
}
}
// Return empty result instead of throwing
return new EmbeddingSearchResult<>(Collections.emptyList());
}
}
}try {
// First embedding: 3 dimensions
store.add(Embedding.from(new float[]{0.1f, 0.2f, 0.3f}));
// Second embedding: 4 dimensions (will fail)
store.add(Embedding.from(new float[]{0.1f, 0.2f, 0.3f, 0.4f}));
} catch (RuntimeException e) {
if (e.getMessage().contains("dimension")) {
System.err.println("Embedding dimension mismatch");
// Action: Ensure all embeddings have same dimensions
}
}Prevention:
public class EmbeddingValidator {
private Integer expectedDimension = null;
public void validateAndAdd(Embedding embedding) {
int dimension = embedding.vector().length;
if (expectedDimension == null) {
expectedDimension = dimension;
} else if (dimension != expectedDimension) {
throw new IllegalArgumentException(
"Expected dimension " + expectedDimension +
" but got " + dimension
);
}
store.add(embedding);
}
}try {
// Invalid: comparison operator on string
Filter filter = metadataKey("name").isGreaterThan("M");
EmbeddingSearchRequest request = EmbeddingSearchRequest.builder()
.queryEmbedding(queryEmbedding)
.filter(filter)
.build();
store.search(request);
} catch (RuntimeException e) {
System.err.println("Invalid filter: " + e.getMessage());
// Action: Use isEqualTo or isIn for string values
}Prevention:
// For strings, use equality or collection filters
Filter validFilter = metadataKey("name").isEqualTo("Smith");
Filter validFilter2 = metadataKey("name").isIn(names);
// For numbers, comparison operators work
Filter numericFilter = metadataKey("year").isGreaterThan(2020);try {
store.search(request);
} catch (RuntimeException e) {
String message = e.getMessage().toLowerCase();
if (message.contains("collection")) {
System.err.println("Collection error: " + e.getMessage());
// Collection may have been deleted or corrupted
} else if (message.contains("404") || message.contains("not found")) {
System.err.println("Resource not found: " + e.getMessage());
} else if (message.contains("500") || message.contains("internal server")) {
System.err.println("Chroma server error: " + e.getMessage());
// Check Chroma server logs
} else {
System.err.println("Unknown error: " + e.getMessage());
}
}public class BatchProcessor {
public List<String> addAllWithErrorHandling(
List<Embedding> embeddings,
List<TextSegment> segments
) {
try {
return store.addAll(embeddings, segments);
} catch (Exception e) {
System.err.println("Batch add failed: " + e.getMessage());
// Fallback: add individually to identify failures
List<String> ids = new ArrayList<>();
for (int i = 0; i < embeddings.size(); i++) {
try {
String id = store.add(embeddings.get(i), segments.get(i));
ids.add(id);
} catch (Exception itemError) {
System.err.println("Failed item " + i + ": " +
itemError.getMessage());
ids.add(null); // Mark failure
}
}
return ids;
}
}
}public void addAllInChunks(
List<Embedding> embeddings,
List<TextSegment> segments,
int chunkSize
) {
for (int i = 0; i < embeddings.size(); i += chunkSize) {
int end = Math.min(i + chunkSize, embeddings.size());
try {
List<Embedding> embBatch = embeddings.subList(i, end);
List<TextSegment> segBatch = segments.subList(i, end);
store.addAll(embBatch, segBatch);
System.out.println("Processed chunk " + (i / chunkSize + 1));
} catch (Exception e) {
System.err.println("Chunk " + (i / chunkSize + 1) +
" failed: " + e.getMessage());
// Continue with next chunk or handle failure
}
}
}public class MonitoredStore {
private final ChromaEmbeddingStore store;
private final Logger logger;
public String add(Embedding embedding, TextSegment segment) {
long startTime = System.currentTimeMillis();
try {
String id = store.add(embedding, segment);
long duration = System.currentTimeMillis() - startTime;
logger.info("Add successful - duration: {}ms", duration);
return id;
} catch (java.net.http.HttpTimeoutException e) {
long duration = System.currentTimeMillis() - startTime;
logger.error("Add timeout after {}ms: {}", duration, e.getMessage());
throw e;
} catch (Exception e) {
logger.error("Add failed: {}", e.getMessage(), e);
throw e;
}
}
}public class MetricsStore {
private final AtomicLong successCount = new AtomicLong();
private final AtomicLong failureCount = new AtomicLong();
private final AtomicLong totalDuration = new AtomicLong();
public String addWithMetrics(Embedding embedding, TextSegment segment) {
long start = System.currentTimeMillis();
try {
String id = store.add(embedding, segment);
successCount.incrementAndGet();
totalDuration.addAndGet(System.currentTimeMillis() - start);
return id;
} catch (Exception e) {
failureCount.incrementAndGet();
throw e;
}
}
public void printMetrics() {
long success = successCount.get();
long failure = failureCount.get();
long total = success + failure;
long avgDuration = total > 0 ? totalDuration.get() / success : 0;
System.out.println("Success: " + success);
System.out.println("Failure: " + failure);
System.out.println("Success rate: " +
(total > 0 ? (success * 100.0 / total) : 0) + "%");
System.out.println("Avg duration: " + avgDuration + "ms");
}
}@Test
public void testConnectionError() {
// Use invalid URL to test connection error handling
ChromaEmbeddingStore store = ChromaEmbeddingStore.builder()
.baseUrl("http://invalid-host:9999")
.timeout(Duration.ofSeconds(1))
.build();
assertThrows(Exception.class, () -> {
store.add(Embedding.from(new float[]{1.0f, 0.0f, 0.0f}));
});
}
@Test
public void testTimeoutError() {
ChromaEmbeddingStore store = ChromaEmbeddingStore.builder()
.baseUrl("http://localhost:8000")
.timeout(Duration.ofMillis(1)) // Very short timeout
.build();
// May timeout with large operations
List<Embedding> largeList = generateLargeEmbeddingList();
assertThrows(java.net.http.HttpTimeoutException.class, () -> {
store.addAll(largeList);
});
}Install with Tessl CLI
npx tessl i tessl/maven-dev-langchain4j--langchain4j-chroma@1.11.0